【问题标题】:Get all the rejected additions to a Set将所有被拒绝的添加到 Set
【发布时间】:2017-06-13 05:00:25
【问题描述】:

我不太擅长哈希集,我想知道我是否能够使用 .addAll 方法检索哈希集删除的重复项。所以在我的代码中,它要求用户输入不超过 20 的值,如果是 -1,则中断。然后它会删除重复项并显示完成的列表。但现在我想显示已删除重复项的列表。例如:2 = 3 个重复 5 = 5 个重复。这是我的代码:

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Scanner;
import java.util.Set;

public class Question {
    public static void main(String[] args) {
        ArrayList<Integer> entries = new ArrayList<Integer>();
        Scanner input = new Scanner(System.in);
        int counter = 0;
        int sentinel = -1;
        while (entries.size() <= 20) {

            System.out.println("Please enter some numbers into the entries list");
            entries.add(input.nextInt());
            if (entries.get(counter) == sentinel) {
                entries.remove(counter);
                break;
            }
            System.out.println("You've added: " + entries.get(counter) + ". So far your list is as shows: " + entries);
            counter++;

        }

        System.out.println("The list is: " + entries);
        System.out.println("Checking for Duplicates...");

        Set<Integer> num = new LinkedHashSet<>(entries);
        num.addAll(entries); // The addAll method deletes duplicates
        System.out.println(num);
        entries.clear();
        entries.addAll(num);

        System.out.println("The Finished list is: " + entries);

    }

}

【问题讨论】:

标签: java list arraylist duplicates hashset


【解决方案1】:

很遗憾,Set 不会跟踪它拒绝的所有项目。您必须手动执行此操作。一种快速而肮脏的方法如下:

Set<Integer> noDuplicates = new LinkedHashSet<Integer>();
List<Integer> rejects = new ArrayList<Integer>();
for(Integer entry : entry) {
   if(!noDuplicates.add(entry)) { rejects.add(entry) }
}

请注意,当尝试将重复元素添加到 Set 时,add 方法会返回 false 并拒绝添加请求。

【讨论】:

    【解决方案2】:

    除了what CKing suggests,这是正确的,您可能还对使用 Guava 的Multiset 感兴趣。该系列专为您所描述的问题而构建。您只需使用 add() 方法添加元素(就像您已经做的那样):

    Multiset<Integer> entries = HashMultiset.create();
    entries.add(1);
    entries.add(1);
    ...
    

    然后,要计算重复项,您可以这样做:

    for (Integer entry : entries.elementSet()) {
         int count = entries.count(entry);
         if (count > 1) {
             System.out.println(entry +" = "+count+" duplicates");
         }
    }
    

    Multiset(也称为“Bag”)保留重复元素,并且可以轻松返回每个元素的出现次数。如果你想要 Set 的(唯一)元素,你可以简单地调用elementSet(),如上所示。

    当然,前提是您不介意导入外部库。

    【讨论】:

    • 对于这么简单的任务似乎有点过头了?
    • 当然,但它可能更容易阅读。我不认为这是最有效的选择。您的答案是正确的,只是补充说作为替代
    • 我猜还不错。
    • 其实,它毕竟可能没有那么大的矫枉过正:) 它只是承担了添加外部库的成本,原因很小。仅当我的程序的其他部分也需要 Guava 时,我才会遵循此解决方案
    【解决方案3】:

    在我看来,您使用 Set 只是因为它的性质不允许重复。

    我相信List 可能与您的Set 一样好。您正在对您的数据进行一些统计。没关系。

    一些示例代码仅通过使用 Java 8 的列表来显示您的统计信息:

    1. 收集唯一值

      entries.stream()
          .distinct()
          .collect(Collectors.toSet()); // or list or array or whatever you prefer
      
    2. 只收集重复项

      entries.stream()
          .filter(i -> Collections.frequency(entries, i) > 1)
          .collect(Collectors.toSet());
      

    如果您希望立即将它们打印出来,请省略 .collect(...) 并改用 .forEach(System.out::println) 之类的东西。

    如果您因任何原因不能使用 Java 8,另一种获取重复列表的简单方法也是:

    // unique values:
    Set<Integer> uniqueEntries = new HashSet<>(entries);
    
    // get only the duplicates:
    List<Integer> duplicates = new ArrayList<>(entries);
    duplicates.removeAll(uniqueEntries);
    

    如果您真的很喜欢 Set 以了解您需要实现自己的 Set 的重复数量,它为您添加的每个重复项保存一个计数器。

    【讨论】:

    • 如果不确定,最好询问 OP 他们是否使用java-8
    • 真的需要吗? Guava 也是一个答案,OP 也可能不会使用(或不可用)它,它仍然可以帮助其他人找到最合适的解决方案。尽管如此,消息保持不变。如果只是为了统计,为什么不使用List 而不是Set?我将在答案中添加一个非 java-8 示例:-)
    • 如果 OP 不能使用 java-8Guava,您的答案将立即失效。我要说明的一点是,在发布专门的答案或至少在您的答案中提到 此解决方案将适用于 java-8 或 Guava 之前,请始终询问。
    • @CKing Java 7 已经报废了将近 2 年。我想除非他们另有说明,否则假设有人使用 Java 8 是安全的。
    • @SeanPatrickFloyd 无论多么安全或不安全的假设仍然是一个假设。许多组织和客户不考虑报废。还有很多因素在起作用。在发布专门的答案或至少明确提及该代码仅适用于最新版本之前,最好先询问
    【解决方案4】:

    如果你使用 entries.add(),如果条目已经存在,它将返回 false。所以你不需要使用 addAll() 方法,而是通过调用 entries.add() 来“手动”添加每个元素并计算它返回 false 的次数。

    阅读更多关于它的信息here

    顺便说一句。 addAll() 也只是迭代给定的列表并为每个条目调用 add() ;-)

    【讨论】:

    • 这对我帮助很大!谢谢。因此,当我让它返回 false 时,我创建了另一个列表来保存 valueOfDuplicate,如果 valueOfDuplicate 列表中已经存在重复项,我将其放入 copyOfDuplicate,然后将两个列表存储到一个完整的列表中。
    • 如果您没有更多问题,最好将此标记为已回答。
    【解决方案5】:

    你可以创建

    ArrayList<Integer> duplicates = new ArrayList<Integer>();
    

    然后当你添加它时,你只需检查它是否已经在数组中,如果是,你将它添加到重复数组中

    in=input.nextInt();
    entries.add(in);
        if (entries.get(counter) == sentinel) {
            if(entries.contains(in))
                Duplicates.add(entries);
            entries.remove(counter);
            break;
            }
    

    编辑:Cking 的答案更好,但我会保留它,因为它可能会让您了解正在发生的事情,因为它更接近您的代码。

    【讨论】:

    • 这里发生了什么:(
    • 只是创建一个重复列表。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-13
    • 2014-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多