java—如何计算arraylist中元素的单个出现次数?

pexxcrt2  于 2021-06-27  发布在  Java
关注(0)|答案(5)|浏览(373)

我试着找出哪些数字在一个列表中出现过一次。例如,[1,3,2,3]的列表应该返回[1,2]。但是,我的代码只返回[1],当我还尝试打印副本时,它打印了[3,2]。
我不确定哪里出了错,因为我一直在跟踪重复的元素,以确保一个元素不会计数两次。
还有更有效的方法吗?例如,使用hashmap?我知道我可以使用collections类,但为了练习,我宁愿避免使用它!
任何帮助和建议都将不胜感激。
以下是我的资料:

import java.util.*;

class Main {
  public static void main(String[] args) {
    // From a list find which numbers appear once
    ArrayList<Integer> list = new ArrayList<Integer>();
    list.add(1);
    list.add(3);
    list.add(2);
    list.add(3);

    ArrayList<Integer> once = new ArrayList<Integer>();
    boolean isDuplicate = false;
    ArrayList<Integer> duplicate = new ArrayList<Integer>();

    for (int i=0; i<list.size(); i++) {
      if (!duplicate.contains(list.get(i))){ // if its not a duplicate, continue iterating through the list
        for (int j=i+1; j<list.size(); j++) {
          if (list.get(i).equals(list.get(j))) { // if its a duplicate
            isDuplicate = true;
          }
        }
        if (!isDuplicate) { // if its not a duplicate add to the "once" list
            once.add(list.get(i));
        } else { // if isDuplicate is true add to the duplicate list
            duplicate.add(list.get(i));
        }
          }
    }
    System.out.println("Numbers that appear once: " + once + "\nDuplicates: " + duplicate);
}
xfb7svmp

xfb7svmp1#

答案迟了,但一般建议使用 Set 因为 add 当元素已经存在于集合中时,集合的方法返回false,因此不需要使用 contains 方法。

Set<Integer> once = new LinkedHashSet<>(); // use LinkedHashMap to keep insertion order
Set<Integer> duplicates = new LinkedHashSet<>();
for (Integer i : list) {
    if (!once.add(i)) { // duplicate detected
        duplicates.add(i);
    }
}
once.removeAll(duplicates); // remove all duplicates from `once` set
System.out.println("once: " + once);
System.out.println("duplicates: " + duplicates);

输出:

once: [1, 2]
duplicates: [3]

也可以使用javastreamapi(java8+)来构建频率图,使用诸如 groupingBy 以及 summingInt 保持整数或 toMap . 然后可以根据frequency值过滤map条目:如果1,则为single,否则(frequency>1)为duplicate。

Map<Integer, Integer> frequencyMap1 = list.stream()
                                          .collect(Collectors.groupingBy(
                                              x -> x, 
                                              LinkedHashMap::new, 
                                              Collectors.summingInt(x -> 1)
                                          ));
System.out.println("groupingBy: " + frequencyMap1);

Map<Integer, Integer> frequencyMap = list.stream()
                                         .collect(Collectors.toMap(
                                             x -> x, x -> 1, Integer::sum, LinkedHashMap::new
                                         ));
System.out.println("toMap: " + frequencyMap);
System.out.println("once: " + frequencyMap.entrySet().stream().filter(e -> e.getValue() == 1).map(Map.Entry::getKey).collect(Collectors.toList()));
System.out.println("duplicates: " + frequencyMap.entrySet().stream().filter(e -> e.getValue() > 1).map(Map.Entry::getKey).collect(Collectors.toList()));

输出:

groupingBy: {1=1, 3=2, 2=1}
toMap: {1=1, 3=2, 2=1}
once: [1, 2]
duplicates: [3]
z4iuyo4d

z4iuyo4d2#

特别是对于你的代码,你需要重新设置 isDuplicate 如果在每次迭代开始时设置为false,还可以添加 break 将isduplicate设置为true后的语句,以避免验证其余数字(如果您已经知道这是重复的):

for (int i=0; i<list.size(); i++) {
    isDuplicate = false; // reset the variable to false
    if (!duplicate.contains(list.get(i))){
        for (int j=i+1; j<list.size(); j++) {
            if (list.get(i).equals(list.get(j))) {
                isDuplicate = true;
                break; // stops the execution of the current for
            }
        }
        if (!isDuplicate) {
            once.add(list.get(i));
        } else {
            duplicate.add(list.get(i));
        }
    }
}

对于这个问题,如果有一个最有效的方法来做到这一点,有很多种方法,但最简单的方法之一是不使用嵌套的for,您只需询问数字是否存在于once列表中,如果存在,则表示重复,然后您可以删除它并将其添加到重复列表中,就像这样(在本解决方案中) duplicate 必须是类型 Set<Integer> 为避免在原始列表中出现两次以上的数字时出现重复):

for(Integer number : list) {
    if (!once.contains(number) && !duplicate.contains(number)) {
        once.add(number);
    } else {
        once.remove(number);
        duplicate.add(number);
    }
}
cfh9epnr

cfh9epnr3#

您可以比较这些方法的返回值 indexOf 以及 lastIndexOf ,和 filter 输出重复项:

ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(3);
list.add(2);
list.add(3);

ArrayList<Integer> distinct = list.stream()
        .filter(e -> list.indexOf(e) == list.lastIndexOf(e))
        .collect(Collectors.toCollection(ArrayList::new));

System.out.println(distinct); // [1, 2]
wvt8vs2t

wvt8vs2t4#

假设您有以下列表:
arraylist=新建arraylist();
...
如果这些数字只出现一次,您希望将它们保留在列表中。所以如果这个数字是重复的,我们就得把它去掉。
如果您的列表中只有一个数字,那么第一个和最后一个出现的数字将是相同的。我们将使用此选项从列表中删除所有重复项:
list.removeif((number)->list.indexof(number)=list.lastindexof(number));

t0ybt7op

t0ybt7op5#

你需要重新设置 isDuplicate

import java.util.*;

class Main {
  public static void main(String[] args) {
    // From a list find which numbers appear once
    ArrayList<Integer> list = new ArrayList<Integer>();
    list.add(1);
    list.add(3);
    list.add(2);
    list.add(3);

    ArrayList<Integer> once = new ArrayList<Integer>();
    boolean isDuplicate = false;
    ArrayList<Integer> duplicate = new ArrayList<Integer>();

    for (int i=0; i<list.size(); i++) {
      if (!duplicate.contains(list.get(i))){ // if its not a duplicate, continue iterating through the list
        for (int j=i+1; j<list.size(); j++) {
          if (list.get(i).equals(list.get(j))) { // if its a duplicate
            isDuplicate = true;
          }
        }
        if (!isDuplicate) { // if its not a duplicate add to the "once" list
          once.add(list.get(i));
        } else { // if isDuplicate is true add to the duplicate list
          duplicate.add(list.get(i));
          isDuplicate = false;
        }
      }
    }
    System.out.println("Numbers that appear once: " + once + "\nDuplicates: " + duplicate);
  }
}

相关问题