我有一个List,其中包含一个对象列表,我想从这个列表中删除所有在两个属性中具有相同值的元素。我曾做过这样的事情:
List<Class1> myList;
....
Set<Class1> mySet = new HashSet<Class1>();
mySet.addAll(myList);
并重写Class1中的哈希方法,以便返回一个仅取决于我想要考虑的属性的数字。
问题是我需要在应用程序的另一部分进行不同的过滤,所以我不能以这种方式覆盖哈希方法(我需要两种不同的哈希方法)。
在不重写哈希方法的情况下进行此过滤的最有效方法是什么?
由于
答案 0 :(得分:4)
在hashCode
中覆盖equals
和Class1
(只是为了做到这一点)是有问题的。你最终会对你的班级有一个不自然的平等定义,这可能会成为该班级其他当前和未来用途的其他用途。
查看Comparator界面并撰写Comparator<Class1>
实施内容,根据您的条件比较Class1
的实例;例如基于这两个属性。然后使用TreeSet(Comparator)构造函数实例化TreeSet<Class
&gt;`以进行重复检测。
修改强>
将此方法与@Tom Hawtin的方法进行比较:
这两种方法总体上使用大致相当的空间。 treeset的内部节点大致平衡了hashset的数组和支持自定义equals / hash方法的包装器。
对于树集方法,包装器+哈希集方法的时间O(N)
(假设是良好的哈希)与O(NlogN)
。因此,如果输入列表可能很大,那就是要走的路。
树形方法在需要编写的代码行方面获胜。
答案 1 :(得分:3)
让Class1
实施Comparable
。然后在示例中使用TreeSet
(即使用addAll
方法)。
答案 2 :(得分:2)
作为罗马所说的替代方法,您可以查看有关使用谓词过滤的this SO question。无论如何,如果你使用谷歌收藏,这可能是一个不错的选择。
答案 3 :(得分:1)
我建议为Class1
部分的概念引入一个类,您希望在此上下文中考虑这些概念。然后使用HashSet
或HashMap
。
答案 4 :(得分:0)
有时程序员会因为使用语言的所有优点而使事情变得太复杂,而这个问题的答案就是一个例子。覆盖课堂上的任何内容都是过度的。你需要的是:
class MyClass {
Object attr1;
Object attr2;
}
List<Class1> list;
Set<Class1> set=....
Set<MyClass> tempset = new HashSet<MyClass>;
for (Class1 c:list) {
MyClass myc = new MyClass();
myc.attr1 = c.attr1;
myc.attr2 = c.attr2;
if (!tempset.contains(myc)) {
tempset.add(myc);
set.add(c);
}
}
随意修复轻微的irregulairites。根据属性的相等性意味着一些问题(如果属性是原始的,则会有明显的变化)。有时我们需要编写代码,而不仅仅是使用内置库。