Java 处理多个对象而不退回已处理对象的最佳方法是什么?

Java 处理多个对象而不退回已处理对象的最佳方法是什么?,java,arraylist,equals,hashset,hashcode,Java,Arraylist,Equals,Hashset,Hashcode,假设我想在更高级别的算法过程中,使用某种方法处理某类对象的多个对象。在这个算法中,可能会出现相同的对象(没有相同的地址),因此我不想处理这些相同的对象中的每一个,只处理第一个出现的对象,而忽略其他对象 一个简单的解决方案是实现一个ArrayList结构来存储所有已处理的对象,命名为treated,并执行以下操作 if (!treated.contains(o)){ treat(o); treated.add(o); } 但是,我认为contains方法是在线性时间内运行的,而使

假设我想在更高级别的算法过程中,使用某种方法处理某类对象的多个对象。在这个算法中,可能会出现相同的对象(没有相同的地址),因此我不想处理这些相同的对象中的每一个,只处理第一个出现的对象,而忽略其他对象

一个简单的解决方案是实现一个
ArrayList
结构来存储所有已处理的对象,命名为
treated
,并执行以下操作

if (!treated.contains(o)){
    treat(o);
    treated.add(o);
}
但是,我认为
contains
方法是在线性时间内运行的,而使用
HashSet
而不是
ArrayList
可以在恒定时间内运行

但我的问题是:相同的哈希代码不能确保相等。换句话说,使用
HashSet处理
,如下所示:

if (!treated.contains(o)){
    treat(o);
    treated.add(o);
}
可能不会处理所有不同的对象,因为某些对象
o1
可能最终与另一个对象
o2
具有相同的hashcode。如果处理了
o1
,则不会处理
o2
,反之亦然。 与一些
equals()
一起使用的
HashMap处理的
,是否更适合我的问题

if (treated.containsKey(o.hashCode())){
    Object o2 = treated.get(o.hashCode());
    if (!o.equals(o2)){
        treat(o);
    }
} else {
    treat(o);
    treated.put(o.hashCode(), o);
}
解决这个问题的推荐方法是什么

if (treated.containsKey(o.hashCode())){
    Object o2 = treated.get(o.hashCode());
    if (!o.equals(o2)){
        treat(o);
    }
} else {
    treat(o);
    treated.put(o.hashCode(), o);
}
注意:我看到过关于使用“完美哈希代码”的评论,即哈希代码为每个唯一的对象分配一个唯一的值,从而不会为不同的对象获得类似的哈希代码。我不认为这是一个解决方案,因为(从理论上讲)我可以处理任意数量的不同对象,而hashcode的类型是
int
,这有效地限制了不同hashcode的数量

换句话说,使用
HashSet处理
,如下[…]
可能不会处理所有不同的对象,因为某些对象o1可能最终具有相同的
哈希代码作为不同的对象

这是基于一个错误的假设,
HashSet.contains
只检查哈希代码。它没有-它使用散列码查找相等的候选项,然后像正常情况一样使用
equals
检查实际的相等性

从:

如果此集合包含指定的元素,则返回true。更正式地说,当且仅当此集合包含元素e,使得
对象.equals(o,e)
时,返回true


“与一些equals()一起使用的HashMap处理是否更适合我的问题?”->无论如何,您都需要覆盖
.equals
.hashCode
。“一个哈希代码为每个唯一的对象分配一个唯一的值”似乎与哈希代码的观点不一致。你似乎假设一个
HashSet
只查看哈希代码。没有。在
HashSet.contains
的文档中:“更正式地说,当且仅当该集合包含元素e,使得Objects.equals(o,e)时,返回true。”@jonsket由于
HashSet
中没有get方法,我假设
HashSet
s不存储对象,只存储它们的hashcode,这意味着
只包含比较过的哈希代码。显然我想错了!如果我没弄错的话,这就解决了我的问题,我可以简单地使用
哈希集。如果你愿意,你可以发布这个答案。@J.Schmidt:没有
get
方法,因为没有任何键或索引可以获取单个值,但它仍然是一个集合。。。你可以对它进行迭代等等。@J.Schmidt:这是可能的,但它并不存在(我发现有时这很烦人,因为我想保留一组“规范”值),而且它不是正常的“集合”操作的一部分。“按索引获取”或“按键获取”用于列表和映射,这并不是集合固有的方式。作为补充说明,
set
的契约使得像
if(!set.contains(o)){…set.add(o);}
这样的操作过时了。您可以简单地使用
if(treated.add(o))treat(o)