如何从java中的列表中选择重复值?

例如我的列表包含{4,6,6,7,7,8},我想要最终结果= {6,6,7,7}

一种方法是遍历列表并消除唯一值(在这种情况下为4,8)。

有没有其他有效的方式而不是循环列表? 我问过这个问题,因为我工作的清单非常大? 我的代码是

List duplicate = new ArrayList(); for (int i = 0; i < list.size(); i++) { Long item = (Long) list.get(i); if (!duplicate.contains(item)) { duplicate.add(item); } } 

到目前为止一些好的答案,但另一个选择只是为了它的乐趣。 循环遍历列表,尝试将每个数字放入Set,例如HashSet 。 如果add方法返回false,则表示该数字是重复的,应该进入重复列表。

编辑:像这样的东西应该这样做

 Set unique = new HashSet<>(); List duplicates = new ArrayList<>(); for( Number n : inputList ) { if( !unique.add( n ) ) { duplicates.add( n ); } } 

有没有其他有效的方式而不是循环列表?

你可以聘请一个魔法精灵让它为你做。 如果没有循环,你会怎么做? 如果不循环遍历列表,您甚至无法查看元素。 这就像你想要在不看这些数字的情况下将一大堆数字相加在一起。 求和元素比搜索重复元素或搜索唯一元素要容易得多。 通常,97%的代码所做的是循环遍历列表和数据并处理和更新它。

所以,说,你必须循环。 现在您可能想要选择最有效的方式。 一些方法浮现在脑海:

  • 对所有数字进行排序,然后只循环一次以查找重复项(因为它们将彼此相邻)。 但是,请记住,排序算法也会遍历数据。
  • 对于列表中的每个元素,检查是否存在具有相同值的另一个元素。 (这就是你如何做到的。这意味着你们彼此之间有两个循环。(在课程列表中contains循环。))
 List inputList = Arrays.asList(4, 6, 6, 7, 7, 8); List result = new ArrayList(); for(Number num : inputList) { if(Collections.frequency(inputList, num) > 1) { result.add(num); } } 

我不确定效率,但我发现代码易于阅读(这应该是首选。

编辑:将Lists.newArrayList()更改为new ArrayList();

我喜欢回答Java 8,Streams来查找重复的元素 。 解决方案仅返回唯一的重复项。

  Integer[] numbers = new Integer[] { 1, 2, 1, 3, 4, 4 }; Set allItems = new HashSet<>(); Set duplicates = Arrays.stream(numbers) .filter(n -> !allItems.add(n)) //Set.add() returns false if the item was already in the set. .collect(Collectors.toSet()); System.out.println(duplicates); // [1, 4] 

有一个

 Map numberToOccurance = new HashMap(); 

维护计数和数字,最后迭代键集并获得具有多个计数的值

理想情况下,您的List应该是一个不允许重复的Set 。 作为循环的替代方法,您可以转换并切换到Set或中间使用它来消除重复,如下所示:

 List dupesList = Arrays.asList(4L, 6L, 6L, 7L, 7L, 8L); Set noDupesSet = new HashSet(dupesList); System.out.println(noDupesSet); // prints: [4, 6, 7, 8] // To convert back to List Long[] noDupesArr = noDupesSet.toArray(new Long[noDupesSet.size()]); List noDupesList = Arrays.asList(noDupesArr); System.out.println(noDupesList); // prints: [4, 6, 7, 8] 
 import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; public class FindDuplicate { public static void main(String[] args) { // Load all your ArrayList List list = new ArrayList(); list.add("Jhon"); list.add("Jency"); list.add("Mike"); list.add("Dmitri"); list.add("Mike"); // Set will not allow duplicates Set checkDuplicates = new HashSet(); System.out.println("Actual list " + list); for (int i = 0; i < list.size(); i++) { String items = list.get(i); if (!checkDuplicates.add(items)) { // retain the item from set interface System.out.println("Duplicate in that list " + items); } } } } 

使用Guava和Java 8,它是微不足道和快速的:

 Multiset multiset = HashMultiset.create(list); return list.stream() .filter(i -> multiset.count(i) > 1) .collect(Collectors.toList()); 

第一行使用一种哈希映射计算计数。 其余部分显而易见。

像这样的东西可以模拟multiset:

 HashMap multiset = new HashMap<>(); list.stream().forEach(i -> multiset.compute(i, (ignored, old) -> old==null ? 1 : old+1))); 

鉴于你可以通过循环列表只执行一次,我不会太担心性能。 如果您搜索更高性能的解决方案,那么您可能最终会使代码过于复杂,可读性和可维护性将受到影响。 在一天结束时,如果您想检查整个列表中的重复项,那么您必须访问每个元素。

我建议编写明显的解决方案,看看它是如何运作的。 您可能会惊讶于Java可以快速迭代列表,即使它特别大。

这是我的解决方案版本:

 import java.util.ArrayList; public class Main { public static void main(String[] args) { ArrayList randomNumbers = new ArrayList(); ArrayList expandingPlace = new ArrayList(); ArrayList sequenceOfDuplicates = new ArrayList(); for (int i = 0; i < 100; i++) { randomNumbers.add((int) (Math.random() * 10)); expandingPlace.add(randomNumbers.get(i)); } System.out.println(randomNumbers); // Original list. for (int i = 0; i < randomNumbers.size(); i++) { if (expandingPlace.get(i) == expandingPlace.get(i + 1)) { expandingPlace.add(0); sequenceOfDuplicates.add(expandingPlace.get(i)); sequenceOfDuplicates.add(expandingPlace.get(i + 1)); } } System.out.println(sequenceOfDuplicates); // What was in duplicate there. } } 

它将0到9之间的数字添加到列表中,并将其添加到另一个列表中的“重复”(数字后跟相同的数字)。 您可以使用您的大列表而不是我的randomNumbers ArrayList。