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

时间:2013-06-25 22:30:15

标签: java list duplicates unique

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

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

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

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

13 个答案:

答案 0 :(得分:9)

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

编辑:这样的事情应该这样做

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

答案 1 :(得分:5)

  

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

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

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

  • 对所有数字进行排序,然后只循环一次以查找重复项(因为它们将彼此相邻)。但是,请记住,排序算法也会遍历数据。
  • 对于列表中的每个元素,检查是否存在具有相同值的其他元素。 (这就是你做到的。这意味着你们彼此之间有两个循环。(contains循环遍历当然的列表。))

答案 2 :(得分:4)

List<Number> inputList = Arrays.asList(4, 6, 6, 7, 7, 8);
List<Number> result = new ArrayList<Number>();
for(Number num : inputList) {
   if(Collections.frequency(inputList, num) > 1) {
       result.add(num);
   }
}

我不确定效率,但我觉得代码很容易阅读(这应该是首选。

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

答案 3 :(得分:4)

我喜欢回答Java 8, Streams to find the duplicate elements。解决方案只返回唯一的重复项。

 Integer[] numbers = new Integer[] { 1, 2, 1, 3, 4, 4 };
 Set<Integer> allItems = new HashSet<>();
 Set<Integer> 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]

答案 4 :(得分:1)

有一个

Map<Integer, Integer> numberToOccurance = new HashMap<Integer, Integer>();

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

答案 5 :(得分:0)

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

List<Long> dupesList = Arrays.asList(4L, 6L, 6L, 7L, 7L, 8L);

Set<Long> noDupesSet = new HashSet<Long>(dupesList);
System.out.println(noDupesSet); // prints: [4, 6, 7, 8]

// To convert back to List
Long[] noDupesArr = noDupesSet.toArray(new Long[noDupesSet.size()]);
List<Long> noDupesList = Arrays.asList(noDupesArr);
System.out.println(noDupesList); // prints: [4, 6, 7, 8]

答案 6 :(得分:0)

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<String> list = new ArrayList<String>();
        list.add("Jhon");
        list.add("Jency");
        list.add("Mike");
        list.add("Dmitri");
        list.add("Mike");

        // Set will not allow duplicates
        Set<String> checkDuplicates = new HashSet<String>();

        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);
            }
        }

    }
}

答案 7 :(得分:0)

使用Guava和Java 8,它既简单又快速:

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

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

这样的东西可以模拟multiset:

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

答案 8 :(得分:0)

再次lambda节省了一天:

List<Long> duplicates = duplicate.stream()
  .collect( Collectors.collectingAndThen( Collectors.groupingBy( Function.identity() ),
    map -> {
      map.values().removeIf( v -> v.size() < 2 );  // eliminate unique values (4, 8 in this case)
      return( map.values().stream().flatMap( List::stream ).collect( Collectors.toList() ) );
    } ) );  // [6, 6, 7, 7]


上述解决方案的速度优化版本:

List<Long> duplicates = duplicate.stream().collect( Collectors.collectingAndThen(
    Collectors.groupingBy( Function.identity(), Collectors.counting() ),
    map -> {
      map.values().removeIf( v -> v < 2 );  // eliminate unique values (4, 8 in this case)
      return( map.entrySet().stream().collect( Collector.of( ArrayList<Long>::new, (list, e) -> {
        for( long n = 0; n < e.getValue(); n++ )
          list.add( e.getKey() );
      }, (l1, l2) -> null ) ) );
    } ) );  // [6, 6, 7, 7]

duplicate的长值不保存而是计数-无疑是最快,最节省空间的变体

答案 9 :(得分:0)

以下内容适用于Eclipse Collections

IntBag bag = IntLists.mutable.with(4, 6, 6, 7, 7, 8).toBag().selectDuplicates();

如果要使用装箱值而不是基元,则可以使用以下方法:

Bag<Integer> bag = Lists.mutable.with(4, 6, 6, 7, 7, 8).toBag().selectDuplicates();

注意:我是Eclipse Collections的提交者。

答案 10 :(得分:0)

试试这个:

受到这个答案的启发:https://stackoverflow.com/a/41262509/11256849

for (String s : yourList){
     if (indexOfNth(yourList, s, 2) != -1){
         Log.d(TAG, s);
      }
   }

使用此方法:

public static <T> int indexOfNth(ArrayList list, T find, int nthOccurrence) {
        if (list == null || list.isEmpty()) return -1;
        int hitCount = 0;
        for (int index = 0; index < list.size(); index++) {
            if (list.get(index).equals(find)) {
                hitCount++;
            }
            if (hitCount == nthOccurrence) return index;
        }
        return -1;
    }

答案 11 :(得分:-1)

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

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

答案 12 :(得分:-1)

这是我的解决方案版本:

import java.util.ArrayList;

public class Main {

public static void main(String[] args) {

    ArrayList<Integer> randomNumbers = new ArrayList<Integer>();
    ArrayList<Integer> expandingPlace = new ArrayList<Integer>();
    ArrayList<Integer> sequenceOfDuplicates = new ArrayList<Integer>();

    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。