【问题标题】:How to prevent the adding of duplicate objects to an ArrayList [duplicate]如何防止将重复对象添加到 ArrayList [重复]
【发布时间】:2012-12-20 23:32:01
【问题描述】:

可能重复:
Prevent duplicate entries in arraylist

我有一个特定 C 类的数组列表。

List<C> myList = new ArrayList<C>();

C 类有两个属性,即。

String str1;
String str2;

现在,当我将 C 类型的对象添加到 ArrayList myList 时,我想检查列表中是否已经存在一个对象,其 str1 和 str2 的值与参数值(str1 和 str2)匹配我要添加的对象。

是否有任何有效的方法可以做到这一点,而不必每次都遍历完整列表并检查参数之间的匹配?

【问题讨论】:

  • 使用 java.util.Set 接口,最好使用 TreeSet 实现而不是 List。一套自动照顾您的要求。您只需将字符串值添加到集合中。搜索网络或阅读有关数据结构的书籍,了解 Set 的工作原理。
  • 这里:helpful link

标签: java oop data-structures


【解决方案1】:

当您需要检查重复项或确保唯一值时,请考虑使用类似Set 的数据结构,而不是列表。

您可以选择以下之一 -

  • HashSet

    • 访问速度更快 - 大致来说是 O(1) 访问。
    • 未排序
    • 哈希表用作基础存储。
  • TreeSet

    • 较慢的访问(相对于 HashSet) - O(log(n))
    • 值自动排序。
    • 用作基础存储的红黑树。

自动设置只允许唯一值。尝试添加以前存在的值将会失败。

请注意,要使其正常工作,您需要覆盖 equalshashcode 以告诉 Set 如何比较您的对象。这一步在What issues should be considered when overriding equals and hashCode in Java?有更好的解释

【讨论】:

  • 需要指出的是,当 hashCode 方法返回的值相等时,Set 认为两个对象相等。当您希望两个具有相同内容的不同对象被视为重复时,您需要重写 hashCode 方法,以便根据对象的所有相关字段计算它。
  • 所以,如果我使用 HashSet(我不想要一个排序集),并且如果我尝试添加一个对象,它基本上会检查集合中是否存在另一个相同的对象参数的值?
  • @Philipp 谢谢菲利普。这正是我想要的。我想检查是否存在具有相同内容的另一个对象,而不是根据任何不同的标准这两个对象是否相等。如何覆盖 hashCode 方法?
  • @AbhishekShivkumar 正如 Philipp 所说,您需要覆盖 equalshashcode 以告诉 Set 如何比较您的对象
  • @AbhishekShivkumar 要覆盖 hashCode 方法,请在您的类 C 中创建一个方法 @Override public int hashCode() 并以基于 str1 和 str2 的内容计算整数的方式实现它。当您没有编写好的哈希函数的经验时,您可以采用 str1 和 str2 的 hashCode 方法并以某种方式组合这些值。您可以对它们进行异或或相加,同时对其中一个值进行位移或相乘(这样它们就不能互换)。
【解决方案2】:

您需要重写 C 类中的equals 方法。

例如

public boolean equals(Object c) {
    if(c !instanceof C) {
        return false;
    }

    C that = (C)c;
    return this.str1.equals(that.getStr1()) && this.str2.equals(that.getStr2());
}

然后你可以调用 myList.contains(viz) 来查看列表是否已经包含一个相等的对象。

这是未经测试的,您可能需要一些额外的错误处理。

如果你确实像这样覆盖了 equals 方法,你还应该确保你覆盖了 hashcode() 方法。见:http://www.technofundo.com/tech/java/equalhash.html

编辑: 正如 cmets 中所指出的,set 实现将更加高效,尽管您仍需要覆盖 equals / hashcode 方法,因此上述示例可能最好与上面的 Karthik 答案结合使用。

【讨论】:

  • 应该指出,大多数列表实现类的contains 方法对于大型列表的扩展性很差,因为需要检查列表的每个条目。在这种情况下,大多数 Set 实现都比较出色。
  • 这将遍历整个列表。与 OP 想要避免的手写版本一样低效,但代码更简洁
  • @Karthik,好点,用注释更新了我的答案:)
  • 谢谢,我接受了你的回答,因为我的列表长度不大,时间优化也不是严格限制。我觉得这是编写 equals 方法的一种很好的小方法,只需使用 contains 检查来查看它是否已经存在。它有效!
【解决方案3】:
if (yourList.contains(Object object))
{
    // do not add
}

【讨论】:

  • 应该指出,大多数实现列表的类的 contains 方法对于大型列表的扩展性很差,因为需要检查列表的每个条目。在这种情况下,大多数 Set 实现都比较出色。
猜你喜欢
  • 1970-01-01
  • 2016-08-10
  • 2018-03-02
  • 2020-12-09
  • 2016-10-31
  • 1970-01-01
  • 1970-01-01
  • 2018-08-11
  • 2019-09-01
相关资源
最近更新 更多