情况:
我们假设我有一个这样的课程:
class Person {
public String name;
public String surname;
public age;
}
现在我想根据一些prevoiusly创建的列表(包含一些重复项)创建一个包含一些People的集合。当然,当我创建集合时,我不希望内部有任何重复。
HashSet<Person> mySet = new LinkedHashSet<Person>(listOfPeople);
问题: 让我们假设,在某些情况下,&#34;没有重复&#34; 对我来说意味着&#34;具有不同名称的人&#34; 。在其他情况下&#34;年龄不同的人&#34; 等
我发现HashSet
的{{1}}方法使用add
中的put
:
HashMap
问题:
所以,我知道我应该简单地覆盖public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { // <== !!
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
中的equals
,并记住为对象应该返回相同的Person
,这些对象应该是&#34;等于&#34;根据我的要求。但是,如果我的平等&#34;运行期间的术语变化?
我问,因为在使用hashCode
对系列进行排序时,我可以指定一个自定义Collections.sort
,这使我能够根据情况提供比较逻辑。
是否有任何类比机制或解决方案,使我能够在运行时决定创建一组元素时组件是否相等?
我现在唯一的解决方案是在Person类中定义一些静态Comparator,然后以这种方式覆盖equals方法它使用这个比较器。然后,通过亲自替换比较器我实际上改变了等于逻辑......这有意义吗?
答案 0 :(得分:1)
我现在唯一的解决方案是在Person类中定义一些静态Comparator,然后以这种方式覆盖equals方法它使用这个比较器
不要那样做。 Comparator
合同中的任何内容都不需要将与.equals()
不同的两个对象与非零进行比较。可以放置的唯一约束是如果两个对象是.equals()
然后相互比较它们给出0. Comparable
的实现被认为是“兼容的等于”。但有些类甚至不尊重JDK中的内容(参见BigDecimal
)。
您有两种选择:
SortedSet
。例如TreeSet
允许您在运行时传递Comparator
。 SortedSet
评估两个实例相互比较为0的事实的等价性,无论.equals()
如何。Equivalence
;然后,您的Set
必须包含Equivalence.Wrapper<Person>
类型的成员,而不仅仅是Person
,而您必须.add(eq.wrap(person))
,但这样做有效。答案 1 :(得分:0)
您可以将TreeSet<Person>
与您自己的比较器
答案 2 :(得分:0)
你必须在Person类中修改一下并使用这个自定义的hashSet
public class CustomHashSet extends HashSet {
@Override
public boolean add(Object e) {
boolean flag = true;
Iterator<Object> itr = this.iterator();
while(itr.hasNext()){
if(itr.next().hashCode()==(e.hashCode())){
flag = false;
break;
}
}
if(flag)
flag = flag & super.add(e);
return flag;
}
}
人员类中的修改
public class Person {
public String name;
public String surname;
public int age;
@Override
public boolean equals(Object obj) {
return (this == obj);
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + age;
return result;
}
}
在哈希码方法复制检查中使用您自己的逻辑。
测试
public class TestB {
public static void main(String[] args) {
HashSet a = new CustomHashSet();
Person p = new Person("test","test1",1);
Person p1 = new Person("test","test1",1);
a.add(p);
a.add(p1);
System.out.println(a);
}
} 这将只添加一个不允许的元素重复元素。 希望这对你有所帮助。 U也可以使用类似的接口实现。