我应该使用 "Set" 还是 "List"

should i use "Set" or "List"

我正在学习Java.util.Collection,遇到过如下问答。

Consider the four core interfaces, Set, List, Queue, and Map. For each of the following four assignments, specify which of the four core interfaces is best-suited, and explain how to use it to implement the assignment.

1) Whimsical Toys Inc (WTI) needs to record the names of all its employees. Every month, an employee will be chosen at random from these records to receive a free toy.

教程提供的答案是

Use a List. Choose a random employee by picking a number between 0 and size()-1.

但我只是想知道不应该使用 Set 而不是 List 吗?因为员工是独一无二的个体,我们不希望多次输入同一员工。我的想法是正确的还是我错过了什么?有没有人有什么建议?在此先感谢您的帮助!

But I was just wondering shouldn't Set be used instead of List? Cause employees are unique individuals and we don't want the same employee to be entered multiple times.

虽然员工是独特的个体,但他们的名字可能并不独特。使用 Set 会消除重复项,错误地删除具有相同姓名的不同员工的姓名。

名称可能包含重复项。一组中不能有两个汤姆。

employees are unique individuals and we dont want the same employee to be entered multiple times

这是个好主意,但您所做的假设并未在问题中提供。该问题并未指定名称将被多次输入,因此尝试删除重复输入只会白费力气。

比去重更重要的是您需要从集合中检索一个值,而Set没有简单的方法来做到这一点.您可以遍历它们,但这同样很浪费。 RandomAccess 集合(例如 ArrayList 允许您在常数时间内检索任意元素。

其他答案也提到你不能假设员工有唯一的名字。记住像人这样的东西通常是一件好事,但问题显然假设我们只有唯一的名字,因为如果一个人,你不知道哪个从列表中选择了重复的名称。这就是为什么员工通常在 "real" 应用程序中与唯一 ID 相关联。

列表似乎是更好的选择。列表中的元素可以在恒定时间内访问。如果您使用的是 ArrayList,那么您可以使用 list.get(index) 方法直接获取您想要的员工。

而如果您选择使用 Set,那么您将需要迭代该集合,直到找到随机选择的员工。

例如

int size = empHashSet.size();
int employee = new Random().nextInt(size);
int i = 0;
for(Employee emp : empHashSet)
{
    if (i == employee)
        return emp;
    i = i + 1;
}

因此,List 显然是正确的选择。

首先:如问题评论中所述,更详细地了解问题可能会更有趣。一般来说,使用 ListSet(如 ArrayListHashSet)的具体版本的问题的答案并不那么微不足道。

让我详细说明为什么会这样以及您可能有的想法:

  • 使用 ArrayListArrayList 将是一个很好的解决方案,如果您知道您不添加相同的 Employee 两次给你的 List。如果您确切知道何时可以第二次添加 Employee,这也可能是一个很好的解决方案。在后一种情况下,您可以使用类似以下内容检查员工:

    private List<Employee> employees = new ArrayList<>();
    
    public void addEmployee(final Employee employee, final boolean check) {
        if (check) {
             Employee found = employees.stream().filter(e -> e.equals(employee)).findFirst().orElse(null);
             if (found == null) {
                 this.employees.add(employee);
             }
         } else {
             this.employees.add(employee);
         }
    }
    
  • 使用HashSet:如果添加重复项的机会是一般情况,则速度更快。访问随机选择的 Employee 时速度较慢(请参阅 Varun Risbud 帖子)。

你不应该忘记,在这两种情况下,Employee 必须有一个 equals 函数(参见 What issues should be considered when overriding equals and hashCode in Java?)。此外,当使用 HashSet 时,Employee 的实现也需要覆盖 'hashCode'。

列表似乎是个不错的选择:

为每个用户创建一个对象,名称可以相同,但其他信息可以不同创建一个单独的对象。

将这些对象放在arrayList 下。

覆盖 hashCode 和 equals 以提供您的比较逻辑。

[例如,您可以使用多种方式来比较对象,可能将年龄作为唯一的成员变量之一,或者 需要唯一的员工 ID ,这将解决您的重复问题]

为什么列表有帮助:

  1. 索引
  2. 您可以通过使用 list.contains(object o)(以及您的 equals 和 hashCode 实现)检查对象来避免重复

要 select 一个随机数非常容易,因为它只需要 Math.random 或随机数 class 对象来引用完整列表中的随机整数。