如何防止向ArrayList中添加重复的对象

17

可能是重复问题:
如何防止ArrayList中出现重复元素?

我有一个特定类C的ArrayList。

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

类C有两个属性,分别是:

String str1;
String str2;

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

有没有一种有效的方法可以在不必每次迭代完整列表并检查参数匹配的情况下实现这一点?


3
请使用java.util.Set接口,最好使用TreeSet实现而不是List。Set自动满足您的要求。您只需将字符串值添加到Set中即可。在网络上搜索或阅读有关数据结构的书籍,以了解Set的工作原理。 - Kiran Mohan
1
请看这个有用的链接:helpful link - Grijesh Chauhan
3个回答

40

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

以下是可供选择的内容之一 -

  • HashSet

    • 更快的访问速度-大致为O(1)。
    • 未排序。
    • 散列表用作基本存储。
  • TreeSet

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

Set自动只允许唯一值。添加已存在的值的尝试将失败。

请注意,为使其起作用,您需要覆盖equals和hashcode以告诉Set如何比较您的对象。有关此步骤的更好解释,请参见在覆盖Java中的equals和hashCode时应考虑哪些问题?


3
需要指出的是,当两个对象的 hashCode 方法返回值相等时,一个 Set (集合)会认为它们是相等的。如果你想让具有相同内容但不同对象的两个实例被视为重复数据,就需要重写 hashCode 方法,使其基于对象的所有相关字段进行计算。 - Philipp
所以,如果我使用一个HashSet(我不想要一个排序的集合),并且如果我尝试添加一个对象,它基本上会检查集合中是否存在另一个对象具有相同参数值的情况吗? - London guy
1
要覆盖hashCode方法,请在您的类C中创建一个方法@Override public int hashCode()并以一种基于str1和str2内容计算整数的方式实现它。当您没有编写良好的哈希函数的经验时,可以只使用str1和str2的hashCode方法,并以某种方式组合这些值。您可以XOR或将它们相加,同时也可以位移或乘以其中一个值(以使它们不可互换)。 - Philipp
优秀的参考资料。谢谢! - London guy
@AbhishekShivkumar,欢迎您,他们的解释比我能做到的更好。 - Karthik T
显示剩余2条评论

21
你需要在Class C中覆盖(override) 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 编辑: 正如评论中指出的那样,集合实现将更加高效,虽然您仍需要重写equals / hashcode方法,因此上面的示例最好与上面的Karthik答案一起使用。

2
еә”иҜҘжҢҮеҮәпјҢеӨ§еӨҡж•°е®һзҺ°Listзҡ„зұ»зҡ„containsж–№жі•еңЁеӨ„зҗҶеӨ§еһӢеҲ—иЎЁж—¶жҖ§иғҪиҫғе·®пјҢеӣ дёәйңҖиҰҒжЈҖжҹҘеҲ—иЎЁзҡ„жҜҸдёӘжқЎзӣ®гҖӮеңЁиҝҷз§Қжғ…еҶөдёӢпјҢеӨ§еӨҡж•°Setе®һзҺ°йғҪжӣҙдјҳз§ҖгҖӮ - Philipp
1
这将遍历整个列表。虽然效率不高,但比 OP 想要避免的手写版本更清晰。 - Karthik T
@Karthik,好观点,我在我的答案里更新了一个注释 :) - cowls
谢谢,我接受了你的答案,因为我的列表长度不大,时间优化也不是严格的限制条件。我觉得这是一种很好的编写equals方法的简洁方式,只需使用contains检查是否已经存在即可。它有效! - London guy

13
if (yourList.contains(Object object))
{
    // do not add
}

2
应该指出,大多数实现List的类的contains方法在处理大型列表时性能较差,因为需要检查列表的每个条目。在这种情况下,大多数Set实现都更优秀。 - Philipp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接