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)代码>。