我试图通过修改hashCode()和equals()方法()来在HashSet中添加重复值?
我试过下面的代码
public class dupSet {
static Set set= new HashSet();
@Override
public int hashCode() {
return (int) (100*Math.random());
}
@Override
public boolean equals(Object obj) {
return false;
}
public static void main(String[] args) throws ParseException {
set.add("a");
set.add("b");
set.add("a");
System.out.println(set);
}
}
根据我的理解,对于两个重复的" a" HashSet将首先获取hashCode()以获取正确的存储桶,然后检查equals()的值,如果equals返回true,则它将不会添加,但如果它返回false则会添加。 因此,为了向我的Set添加重复值,我重写equals(),它总是返回false,但仍设置不允许重复值?
答案 0 :(得分:2)
您hashCode
方法始终返回零。看看Math.random()
。
其次,您不会覆盖添加的元素的equals
和hashCode
。您实际上添加了String
。要使工作正常,您必须实现一个类并将该类的实例添加到HashSet
。实现的类需要覆盖equals
和hashSet
方法,而不是主类。
第三,正如评论中所述,你不应该做你正在做的事情。你真正想要的是ArrayList
。通过这种方式实施equals
和hashCode
方法,基本合同就会被打破。
答案 1 :(得分:1)
你希望Set中的对象包含我认为的重复项(如果只是为了好奇心继续阅读,否则只需选择其他集合。this可能有帮助)
让我做一些更正:
public class DupSet<E extends Comparable<E>>{
private Set<E> mySet = new HashSet<>();
//Implement add, remove and size
}
public class MyNeverEqualClass implements Comparable<MyNeverEqualClass>{
private static int stupidHash = 0;
private int num;
public MyNeverEqualClass(int num){
this.num = num;
}
@Override
public int compareTo(MyNeverEqualClass other){
double rnd = Math.random()*3 + 1
return (rnd > 1.5)? 1:-1;
}
@Override
public boolean equals(MyNeverEqualClass other){
return false;
}
@Override
public int hashCode(){
return stupidHash++;
}
}
public static void main(String[] args){
MyNeverEqualClass a = new MyNeverEqualClass(1);
MyNeverEqualClass b = new MyNeverEqualClass(1);
DupSet<MyNeverEqualClass> set = new DupSet<>();
set.add(a);
set.add(b);
}
答案 2 :(得分:1)
我阅读了源代码,从中我能够理解它的工作原理 所以需要一些帮助
首先
Set是定义明确且不同的对象的集合
所以不存在添加重复值的问题。但是如果你有兴趣了解java如何实现/实现这个约束,那么你可以开始挖掘源代码。
HashSet由HashMap支持,这意味着它将其添加,删除等操作委托给HashMap
。现在当您调用set.add("a");
时
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
调用,然后调用HashMap#put
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
put
方法首先使用
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
一旦计算出hashCode,它就会调用
final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict)
在这个方法里面,它把值放在这个条件
if ((p = tab[i = (n - 1) & hash]) == null)
为true,然后递增modCount
(存储HashMap结构修改的次数),检查是否需要resize
地图,然后调用afterNodeInsertion
并返回null
现在当你调用set.add("b");
时,相同的逻辑再次运行,但这次是final V putVal
方法中的条件
if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
保持为真,因此,代码
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
检测现有映射,从而返回oldValue
。因此阻止添加重复值。