【问题标题】:Identify duplicates in a List识别列表中的重复项
【发布时间】:2011-11-16 21:33:30
【问题描述】:

我有一个整数类型的列表,例如:

[1, 1, 2, 3, 3, 3]

我想要一个返回所有重复项的方法,例如:

[1, 3]

最好的方法是什么?

【问题讨论】:

  • 输入列表是否保证排序(如您的示例)?
  • 对列表进行排序,然后遍历它,保留当前值和先前值。如果当前 == 之前您有重复。
  • 不,列表不一定是排序的。

标签: java collections


【解决方案1】:

Setadd 方法返回一个布尔值是否已经存在(如果不存在则返回 true,如果已经存在则返回 false,请参阅 Set documentation)。

所以只需遍历所有值:

public Set<Integer> findDuplicates(List<Integer> listContainingDuplicates)
{ 
  final Set<Integer> setToReturn = new HashSet<>(); 
  final Set<Integer> set1 = new HashSet<>();

  for (Integer yourInt : listContainingDuplicates)
  {
   if (!set1.add(yourInt))
   {
    setToReturn.add(yourInt);
   }
  }
  return setToReturn;
}

【讨论】:

  • 为什么有setToReturn?你不能只使用 set1.add(yourInt) 并返回 set1 吗?
  • 是的。但是当一个元素在指定列表中只出现一次时,该元素也会被添加。查看问题中的示例:我的解决方案将返回 [1,3],因为数字 2 插入到了 set1 中,但没有插入到 setToReturn 中。您的解决方案将返回 [1,2,3] (这不是要求)
  • 我建议您使用for (Integer yourInt,以避免不必要的装箱和拆箱,特别是因为您的输入已经包含Integers。
  • @JonasThelemann 集合的整个想法是它不能包含重复项。因此:无论您添加 3 的频率如何,它总是只会出现一次。
  • 顺便说一下,如果是HashSet,您还必须考虑负载因子,例如当您指定 100 的初始容量时,因为您要添加该数量的元素,它会四舍五入到 2 的下一个幂 (128),这意味着默认负载因子为 0.75f,调整大小阈值为96,因此在您添加100 元素之前会有调整大小。值得庆幸的是,调整大小不再那么昂贵了。使用最新的 JRE,调整大小不再是重新散列,元素只是根据相关位分布在它们两个可能的结果位置之间。
【解决方案2】:

我也需要一个解决方案。我使用了 leifg 的解决方案并使其通用。

private <T> Set<T> findDuplicates(Collection<T> collection) {

    Set<T> duplicates = new LinkedHashSet<>();
    Set<T> uniques = new HashSet<>();

    for(T t : collection) {
        if(!uniques.add(t)) {
            duplicates.add(t);
        }
    }

    return duplicates;
}

【讨论】:

  • 我知道这是 3 年后的事了,但是为什么是 LinkedHashedSet,即你为什么关心订单?
  • @AhmadRagab 你是对的,LinkedHashSet 不是必需的,除非你关心找到重复项的顺序(我想我当时这样做了)
  • 感谢您的关注!
  • 如果您有太多的输入数据想要使用这个最佳解决方案(而不是对输入进行排序),那么您还需要预先分配 HashSet() 对象的大小。如果没有预分配,插入 HashSet() 时不会获得 O(1) 插入时间。这是因为内部哈希数组会反复调整大小。然后插入平均到 O(log N) 时间。这意味着处理所有 N 个项目变成了 O(N log N),而本来可以是 O(N)。
  • 我认为这是我经常查找的代码 sn-ps 之一 :)
【解决方案3】:

我采用了 John Strickler 的解决方案并重新制作它以使用 JDK8 中引入的流 API:

private <T> Set<T> findDuplicates(Collection<T> collection) {
    Set<T> uniques = new HashSet<>();
    return collection.stream()
        .filter(e -> !uniques.add(e))
        .collect(Collectors.toSet());
}

【讨论】:

  • 这有点难读,不是吗?您在流操作中产生了副作用,因此很难推理。但这只是我想的功能风格。它很简洁,可能是最短的方法;)。
  • 对于大型列表,您可以让它在多个线程上并行执行吗?
  • @froginvasion 内置的distinct() 方法也是有状态的。想不出一个没有状态的高效 (O(n)) 独特操作。
【解决方案4】:

java 8 基础解决方案:

List duplicates =    
list.stream().collect(Collectors.groupingBy(Function.identity()))
    .entrySet()
    .stream()
    .filter(e -> e.getValue().size() > 1)
    .map(Map.Entry::getKey)
    .collect(Collectors.toList());

【讨论】:

  • 输入列表被转换为地图,(按相同值分组)。然后具有唯一值的映射值被“删除”然后使用键映射,然后列表列表转换为列表
  • 美观快速的解决方案,可直接修改为对item的特定getter进行过滤
  • 使用计数怎么样? stream() .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) .entrySet().stream().filter(e -&gt; e.getValue() &gt; 1) .map(Map.Entry::getKey).collect(Collectors.toList())
【解决方案5】:

这是使用 Java 8 的 Streams 的解决方案

// lets assume the original list is filled with {1,1,2,3,6,3,8,7}
List<String> original = new ArrayList<>();
List<String> result = new ArrayList<>();

您只需查看该对象的频率是否在您的列表中不止一次。 然后调用 .distinct() 以在结果中仅包含唯一元素

result = original.stream()
    .filter(e -> Collections.frequency(original, e) > 1)
    .distinct()
    .collect(Collectors.toList());
// returns {1,3}
// returns only numbers which occur more than once

result = original.stream()
    .filter(e -> Collections.frequency(original, e) == 1)
    .collect(Collectors.toList());
// returns {2,6,8,7}
// returns numbers which occur only once

result = original.stream()
    .distinct()
    .collect(Collectors.toList());
// returns {1,2,3,6,8,7}
// returns the list without duplicates

【讨论】:

  • 这在可读性方面很好,但它真的不利于性能。 Collections::frequency 是 O(n)。它需要遍历整个集合才能找到一个项目的频率。我们为集合中的每个项目调用一次,这使得这些 sn-ps O(n^2)。您会注意到任何多个元素的集合的差异。我永远不会在实际代码中使用它。
【解决方案6】:
int[] nums =  new int[] {1, 1, 2, 3, 3, 3};
Arrays.sort(nums);
for (int i = 0; i < nums.length-1; i++) {

    if (nums[i] == nums[i+1]) {
        System.out.println("duplicate item "+nums[i+1]+" at Location"+(i+1) );
    }

}

显然,您可以对它们做任何您想做的事情(即放入一个 Set 以获得重复值的唯一列表)而不是打印...这也有记录重复项的位置的好处。

【讨论】:

    【解决方案7】:

    在 Java 8 上使用番石榴

    private Set<Integer> findDuplicates(List<Integer> input) {
        // Linked* preserves insertion order so the returned Sets iteration order is somewhat like the original list
        LinkedHashMultiset<Integer> duplicates = LinkedHashMultiset.create(input);
    
        // Remove all entries with a count of 1
        duplicates.entrySet().removeIf(entry -> entry.getCount() == 1);
    
        return duplicates.elementSet();
    }
    

    【讨论】:

      【解决方案8】:

      这也有效:

      public static Set<Integer> findDuplicates(List<Integer> input) {
          List<Integer> copy = new ArrayList<Integer>(input);
          for (Integer value : new HashSet<Integer>(input)) {
              copy.remove(value);
          }
          return new HashSet<Integer>(copy);
      }
      

      【讨论】:

      • 它可以工作,但是速度很慢,因为在数组列表上调用 remove() 是线性搜索。
      • 真的。请注意,如果您的输入包含许多重复项,则对性能的影响要小于只有几个重复项。
      【解决方案9】:

      你可以这样使用:

      List<Integer> newList = new ArrayList<Integer>();
      for(int i : yourOldList)
      {
          yourOldList.remove(i);
          if(yourOldList.contains(i) && !newList.contains(i)) newList.add(i);
      }
      

      【讨论】:

      • 这里使用List是很无效的
      • 不要让我开始在这里使用int 作为变量类型。这意味着对于每一次迭代,一个 Integer 被拆箱一次,一个 int 被装箱四次!
      • 我认为在迭代时尝试从列表中删除元素时,您可以轻松获得 ConcurrentModificationException
      • 这是 100% ConcurrentModificationException,因为您遍历列表并动态删除元素。
      【解决方案10】:

      Lambas 可能是一个解决方案

      Integer[] nums =  new Integer[] {1, 1, 2, 3, 3, 3};
      List<Integer> list = Arrays.asList(nums);
      
      List<Integer> dps = list.stream().distinct().filter(entry -> Collections.frequency(list, entry) > 1).collect(Collectors.toList());
      

      【讨论】:

      • 有效,但它为每个条目运行 Collections.frequency,因此速度很慢。
      【解决方案11】:

      使用 MultiMap 将每个值存储为键/值集。然后遍历键并找到具有多个值的键。

      【讨论】:

        【解决方案12】:

        与此处的一些答案类似,但如果您想根据某些属性查找重复项:

          public static <T, R> Set<R> findDuplicates(Collection<? extends T> collection, Function<? super T, ? extends R> mapper) {
            Set<R> uniques = new HashSet<>();
            return collection.stream()
                .map(mapper)
                .filter(e -> !uniques.add(e))
                .collect(toSet());
          }
        

        【讨论】:

          【解决方案13】:

          如果你使用Eclipse Collections,这将起作用:

          MutableList<Integer> list = Lists.mutable.with(1, 1, 2, 3, 3, 3);
          Set<Integer> dupes = list.toBag().selectByOccurrences(i -> i > 1).toSet();
          Assert.assertEquals(Sets.mutable.with(1, 3), dupes);
          

          更新:从 Eclipse Collections 9.2 开始,您现在可以使用 selectDuplicates

          MutableList<Integer> list = Lists.mutable.with(1, 1, 2, 3, 3, 3);
          Set<Integer> dupes = list.toBag().selectDuplicates().toSet();
          Assert.assertEquals(Sets.mutable.with(1, 3), dupes);
          

          您也可以使用原始集合来完成此操作:

          IntList list = IntLists.mutable.with(1, 1, 2, 3, 3, 3);
          IntSet dupes = list.toBag().selectDuplicates().toSet();
          Assert.assertEquals(IntSets.mutable.with(1, 3), dupes);
          

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

          【讨论】:

            【解决方案14】:
            public class practicese {
                   public static void main(String[] args) {   
            
                       List<Integer> listOf = new ArrayList<Integer>();
                       listOf.add(3);
                       listOf.add(1);
                       listOf.add(2);
                       listOf.add(3);
                       listOf.add(3);
                       listOf.add(2);
                       listOf.add(1);
            
                       List<Integer> tempList = new ArrayList<Integer>();
                       for(Integer obj:listOf){
                            if(!tempList.contains(obj)){
                                tempList.add(obj);
            
                            }
                        }
                        System.out.println(tempList);
            
                }
            
            }
            

            【讨论】:

            • 我喜欢这个答案,只需添加一个 else 即可将副本保存在另一个列表中。谢谢
            【解决方案15】:

            创建Map&lt;Integer,Integer&gt;,迭代列表,如果元素在地图中,则增加它的值,否则将其添加到地图中key=1
            迭代地图,并将所有 key>=2 的元素添加到列表中

            public static void main(String[] args) {
                    List<Integer> list = new LinkedList<Integer>();
                    list.add(1);
                    list.add(1);
                    list.add(1);
                    list.add(2);
                    list.add(3);
                    list.add(3);
                    Map<Integer,Integer> map = new HashMap<Integer, Integer>();
                    for (Integer x : list) { 
                        Integer val = map.get(x);
                        if (val == null) { 
                            map.put(x,1);
                        } else {
                            map.remove(x);
                            map.put(x,val+1);
                        }
                    }
                    List<Integer> result = new LinkedList<Integer>();
                    for (Entry<Integer, Integer> entry : map.entrySet()) {
                        if (entry.getValue() > 1) {
                            result.add(entry.getKey());
                        }
                    }
                    for (Integer x : result) { 
                        System.out.println(x);
                    }
            
                }
            

            【讨论】:

            • 这个不错。如果您需要知道有多少重复项,这是最好的解决方案。一些注意事项: (1) 在执行 put() 之前,您不需要调用 remove()。 (2) 您可以从数组中设置 LinkedList,而不是使用重复的 add() 调用。 (3) 当 val != null 时,您可以立即将 x 添加到结果中。结果可能是一个集合或一个列表,具体取决于您是否要计算重复的数量。
            【解决方案16】:

            这应该适用于已排序和未排序。

            public void testFindDuplicates() {
            
                List<Integer> list = new ArrayList<Integer>();
                list.add(1);
                list.add(1);
                list.add(2);
                list.add(3);
                list.add(3);
                list.add(3);
            
                Set<Integer> result = new HashSet<Integer>();
                int currentIndex = 0;
                for (Integer i : list) {
                    if (!result.contains(i) && list.subList(currentIndex + 1, list.size()).contains(i)) {
                        result.add(i);
                    }
                    currentIndex++;
                }
                assertEquals(2, result.size());
                assertTrue(result.contains(1));
                assertTrue(result.contains(3));
            }
            

            【讨论】:

            • 在 ArrayList 的 subList 上调用 contains() 代价高昂,因为它是线性搜索。所以这对于 10 个项目来说是可以的,但对于 1000 万个项目来说是不行的。
            【解决方案17】:

            顶答案的精简版,还添加了空检查和预分配的Set size:

            public static final <T> Set<T> findDuplicates(final List<T> listWhichMayHaveDuplicates) {
                final Set<T> duplicates = new HashSet<>();
                final int listSize = listWhichMayHaveDuplicates.size();
                if (listSize > 0) {
                  final Set<T> tempSet = new HashSet<>(listSize);
                  for (final T element : listWhichMayHaveDuplicates) {
                    if (!tempSet.add(element)) {
                      duplicates.add(element);
                    }
                  }
                }
                return duplicates;
              }
            

            【讨论】:

            • 您需要零校验吗? new HashSet(0) 会返回合理的空集吗?
            • @johnstosh 此代码可以简化,但检查零只允许在必要时使用listSize 初始化tempSet。这是一个小的优化,但我喜欢它。
            【解决方案18】:

            以及使用commons-collectionsCollectionUtils.getCardinalityMap方法的版本:

            final List<Integer> values = Arrays.asList(1, 1, 2, 3, 3, 3);
            final Map<Integer, Integer> cardinalityMap = CollectionUtils.getCardinalityMap(values);
            System.out.println(cardinalityMap
                        .entrySet()
                        .stream().filter(e -> e.getValue() > 1)
                        .map(e -> e.getKey())
                        .collect(Collectors.toList()));
            

            ```

            【讨论】:

              【解决方案19】:

              我接受了 Sebastian 的回答,并在其中添加了一个 keyExtractor -

                  private <U, T> Set<T> findDuplicates(Collection<T> collection, Function<? super T,? extends U> keyExtractor) {
                      Map<U, T> uniques = new HashMap<>(); // maps unique keys to corresponding values
                      return collection.stream()
                          .filter(e -> uniques.put(keyExtractor.apply(e), e) != null)
                          .collect(Collectors.toSet());
                  }
              

              【讨论】:

                【解决方案20】:

                一个线程安全的替代方案是这样的:

                /**
                 * Returns all duplicates that are in the list as a new {@link Set} thread-safe.
                 * <p>
                 * Usually the Set will contain only the last duplicate, however the decision
                 * what elements are equal depends on the implementation of the {@link List}. An
                 * exotic implementation of {@link List} might decide two elements are "equal",
                 * in this case multiple duplicates might be returned.
                 * 
                 * @param <X>  The type of element to compare.
                 * @param list The list that contains the elements, never <code>null</code>.
                 * @return A set of all duplicates in the list. Returns only the last duplicate.
                 */
                public <X extends Object> Set<X> findDuplicates(List<X> list) {
                    Set<X> dups = new LinkedHashSet<>(list.size());
                    synchronized (list) {
                        for (X x : list) {
                            if (list.indexOf(x) != list.lastIndexOf(x)) {
                                dups.add(x);
                            }
                        }
                    }
                    return dups;
                }
                

                【讨论】:

                  【解决方案21】:

                  试试这个来查找列表中的重复项:

                  ArrayList<String> arrayList1 = new ArrayList<String>(); 
                  
                  arrayList1.add("A"); 
                  arrayList1.add("A"); 
                  arrayList1.add("B"); 
                  arrayList1.add("B"); 
                  arrayList1.add("B"); 
                  arrayList1.add("C"); 
                  
                  for (int x=0; x< arrayList1.size(); x++) 
                  { 
                  System.out.println("arrayList1 :"+arrayList1.get(x)); 
                  } 
                  Set s=new TreeSet(); 
                  s.addAll(arrayList1); 
                  Iterator it=s.iterator(); 
                  while (it.hasNext()) 
                  { 
                  System.out.println("Set :"+(String)it.next()); 
                  } 
                  

                  【讨论】:

                  • 是的,这找到了集合,但它没有找到重复项的列表或集合。
                  【解决方案22】:

                  这是一个功能性技术大放异彩的问题。例如,下面的 F# 解决方案比最好的命令式 Java 解决方案更清晰,更不容易出错(我每天都使用 Java 和 F#)。

                  [1;1;2;3;3;3] 
                  |> Seq.countBy id 
                  |> Seq.choose (fun (key,count) -> if count > 1 then Some(key) else None)
                  

                  当然,这个问题是关于 Java 的。所以我的建议是采用一个为 Java 带来功能特性的库。例如,可以使用我的own library 来解决它,如下所示(还有其他几个值得一看):

                  Seq.of(1,1,2,3,3,3)
                  .groupBy(new Func1<Integer,Integer>() {
                      public Integer call(Integer key) {
                          return key;
                      }
                  }).filter(new Predicate<Grouping<Integer,Integer>>() {
                     public Boolean call(Grouping<Integer, Integer> grouping) {
                          return grouping.getGrouping().count() > 1;
                     }
                  }).map(new Func1<Grouping<Integer,Integer>,Integer>() {
                      public Integer call(Grouping<Integer, Integer> grouping) {
                          return grouping.getKey();
                      }
                  });
                  

                  【讨论】:

                  • 然后你会看到 Java 在函数式编程方面实际上仍然很烂。这么简单的问题,用Java很难表达你想要什么。
                  【解决方案23】:
                  public class DuplicatesWithOutCollection {
                  
                      public static void main(String[] args) {
                  
                          int[] arr = new int[] { 2, 3, 4, 6, 6, 8, 10, 10, 10, 11, 12, 12 };
                  
                          boolean flag = false;
                          int k = 1;
                          while (k == 1) {
                  
                              arr = removeDuplicate(arr);
                              flag = checkDuplicate(arr, flag);
                              if (flag) {
                                  k = 1;
                              } else {
                                  k = 0;
                              }
                  
                          }
                  
                      }
                  
                      private static boolean checkDuplicate(int[] arr, boolean flag) {
                          int i = 0;
                  
                          while (i < arr.length - 1) {
                  
                              if (arr[i] == arr[i + 1]) {
                  
                                  flag = true;
                  
                              } else {
                                  flag = false;
                              }
                              i++;
                  
                          }
                  
                          return flag;
                      }
                  
                      private static int[] removeDuplicate(int[] arr) {
                  
                          int i = 0, j = 0;
                          int[] temp = new int[arr.length];
                          while (i < arr.length - 1) {
                  
                              if (arr[i] == arr[i + 1]) {
                  
                                  temp[j] = arr[i + 1];
                                  i = i + 2;
                  
                              } else {
                  
                                  temp[j] = arr[i];
                                  i = i + 1;
                  
                                  if (i == arr.length - 1) {
                                      temp[j + 1] = arr[i + 1];
                                      break;
                                  }
                  
                              }
                              j++;
                  
                          }
                          System.out.println();
                          return temp;
                      }
                  
                  }
                  

                  【讨论】:

                  • 在不使用 Collection 类的情况下实现。但在循环方面几乎不需要改进。志愿服务的帮助是可观的。上面的输出看起来像 --> 2 3 4 6 8 10 11 12
                  • 为了在更短的时间内执行此操作,您需要使用基于哈希的数据结构来跟踪重复项。这就是为什么您会看到使用 HashSet() 的其他解决方案的原因——它内置在 Java 中。
                  • @johnstosh 是的,我知道这一点,但我想在不使用 Collections 的情况下做到这一点,这就是我在评论中提到的原因。如你所见,我在 2017 年 2 月之前已经发表了评论,[有些技术可以您根本不必使用时间复杂度较低的集合]geeksforgeeks.org/…。我在不了解 DS 和算法实践的情况下尝试了该程序。您不必为此投反对票..无论如何谢谢。
                  【解决方案24】:
                  import java.util.Scanner;
                  
                  public class OnlyDuplicates {
                      public static void main(String[] args) {
                          System.out.print(" Enter a set of 10 numbers: ");
                          int[] numbers = new int[10];
                          Scanner input = new Scanner(System.in);
                          for (int i = 0; i < numbers.length; i++) {
                              numbers[i] = input.nextInt();
                          }
                          numbers = onlyDuplicates(numbers);
                          System.out.print(" The numbers are: ");
                          for (int i = 0; i < numbers.length; i++) {
                              System.out.print(numbers[i] + "");
                          }
                      }
                  
                      public static int[] onlyDuplicates(int[] list) {
                          boolean flag = true;
                          int[] array = new int[0];
                          array = add2Array(array, list[0]);
                          for (int i = 0; i < list.length; i++) {
                              for (int j = 0; j < array.length; j++) {
                                  if (list[i] == array[j]) {
                                      flag = false;
                                      break;
                                  }
                              }
                              if (flag) {
                                  array = add2Array(array, list[i]);
                              }
                              flag = true;
                          }
                          return array;
                      }
                      // Copy numbers1 to numbers2
                      // If the length of numbers2 is less then numbers2, return false
                      public static boolean copyArray(int[] source, int[] dest) {
                          if (source.length > dest.length) {
                              return false;
                          }
                  
                          for (int i = 0; i < source.length; i++) {
                              dest[i] = source[i];
                          }
                          return true;
                      }
                      // Increase array size by one and add integer to the end of the array
                      public static int[] add2Array(int[] source, int data) {
                          int[] dest = new int[source.length + 1];
                          copyArray(source, dest);
                          dest[source.length] = data;
                          return dest;
                      }
                  }
                  

                  【讨论】:

                  • 我需要更改哪些内容才能返回重复项?
                  • 这应该作为一个新问题提出。
                  【解决方案25】:

                  这将是查找重复值的好方法,无需使用 Set。

                  public static <T> List<T> findDuplicates(List<T> list){
                  
                  List<T> nonDistinctElements = new ArrayList<>();
                  
                    for(T s : list)
                      if(list.indexOf(s) != list.lastIndexOf(s))
                        if(!nonDistinctElements.contains(s))
                          nonDistinctElements.add(s);
                  
                    return nonDistinctElements;
                  }
                  

                  也就是说,您想要一个返回不同列表的方法,即如果您传递一个元素多次出现的列表,您将获得一个包含不同元素的列表。

                  public static <T> void distinctList(List<T> list){
                  
                  List<T> nonDistinctElements = new ArrayList<>();
                  for(T s : list)
                    if(list.indexOf(s) != list.lastIndexOf(s))
                      nonDistinctElements.add(s);
                  
                  for(T nonDistinctElement : nonDistinctElements)
                    if(list.indexOf(nonDistinctElement) != list.lastIndexOf(nonDistinctElement))
                      list.remove(nonDistinctElement);
                  }
                  

                  【讨论】:

                    【解决方案26】:

                    这段代码怎么样 -

                    public static void main(String[] args) {
                    
                        //Lets say we have a elements in array
                        int[] a = {13,65,13,67,88,65,88,23,65,88,92};
                    
                        List<Integer> ls1 = new ArrayList<>();
                        List<Integer> ls2 = new ArrayList<>();
                        Set<Integer> ls3 = new TreeSet<>();
                    
                        //Adding each element of the array in the list      
                        for(int i=0;i<a.length;i++) {
                         {
                        ls1.add(a[i]);
                        }
                        }
                    
                        //Iterating each element in the arrary
                        for (Integer eachInt : ls1) {
                    
                        //If the list2 contains the iterating element, then add that into set<> (as this would be a duplicate element)
                            if(ls2.contains(eachInt)) {
                                ls3.add(eachInt);
                            }
                            else {ls2.add(eachInt);}
                    
                        }
                    
                        System.out.println("Elements in array or ls1"+ls1); 
                        System.out.println("Duplicate Elements in Set ls3"+ls3);
                    
                    
                    }
                    

                    【讨论】:

                      【解决方案27】:

                      以防万一那些也想包括重复和非重复的人。基本上答案类似于正确答案,但不是从 if not 部分返回,而是返回 else 部分

                      使用此代码(更改为您需要的类型)

                      public Set<String> findDup(List<String> Duplicates){
                          Set<String> returning = new HashSet<>();
                          Set<String> nonreturning = new HashSet<>();
                          Set<String> setup = new HashSet<>();
                          for(String i:Duplicates){
                              if(!setup.add( i )){
                                  returning.add( i );
                              }else{
                                  nonreturning.add( i );
                              }
                          }
                          Toast.makeText( context,"hello set"+returning+nonreturning+" size"+nonreturning.size(),Toast.LENGTH_SHORT ).show();
                          return nonreturning;
                      }
                      

                      【讨论】:

                        【解决方案28】:

                        作为https://*.com/a/52296246变体的更通用的方法

                            /**
                             * Returns a duplicated values found in given collection based on fieldClassifier
                             *
                             * @param collection given collection of elements
                             * @param fieldClassifier field classifier which specifies element to check for duplicates(useful in complex objects).
                             * @param <T> Type of element in collection
                             * @param <K> Element which will be returned from method in fieldClassifier.
                             * @return returns list of values that are duplocated.
                             */
                            public static <T, K> List<K> lookForDuplicates(List<T> collection, Function<? super T, ? extends K> fieldClassifier) {
                        
                                return collection.stream().collect(Collectors.groupingBy(fieldClassifier))
                                                 .entrySet()
                                                 .stream()
                                                 .filter(e -> e.getValue().size() > 1)
                                                 .map(Map.Entry::getKey)
                                                 .collect(Collectors.toList());
                            }
                        

                        【讨论】:

                          【解决方案29】:
                          List.of(1, 1, 3, 4, 5, 5, 6).stream()
                             .collect(Collectors.collectingAndThen
                                           (Collectors.groupingBy(Function.identity()),
                                             map -> map.entrySet()
                                                       .stream()
                                                       .filter(e -> e.getValue().size() > 1)
                                                       .map(Map.Entry::getKey)
                                                       .collect(Collectors.toList())));
                          

                          【讨论】:

                            【解决方案30】:

                            如果您知道最大值(例如

                            伪代码:

                            //does not handle case when mem allocation fails 
                            //probably can be extended to unknown values /larger values .
                            maybe by sorting first
                            public List<int> GetDuplicates(int max)
                            {   
                                //allocate and clear memory to 0/false
                                bit[] buckets=new bit[max]
                                memcpy(buckets,0,max);
                                //find duplicates
                                List<int> result=new List<int>();
                                foreach(int val in List)
                                {
                                    if (buckets[val])
                                    {
                                        result.add(value);
                                    }
                                    else
                                    {
                                        buckets[val]=1;
                                    }
                                }
                                return  result
                            }
                            

                            【讨论】:

                            • 我想你想要“布尔”而不是“位”?您是否在发布代码之前执行了代码?这是一个好的开始。如果您查看 HashSet(),您会发现它是您想要的“桶”实现。