Java 是否可以在HashSet中输入重复值?
我试图通过修改HashSet的hashCode()和equals()方法()在HashSet中添加重复值 我试过下面的代码Java 是否可以在HashSet中输入重复值?,java,set,hashcode,hashset,Java,Set,Hashcode,Hashset,我试图通过修改HashSet的hashCode()和equals()方法()在HashSet中添加重复值 我试过下面的代码 public class dupSet { static Set set= new HashSet(); @Override public int hashCode() { return (int) (100*Math.random()); } @Override public boolean equals(O
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(),以获取正确的bucket,然后检查equals()的值。如果equals返回true,则它将不会添加,但如果它返回false,则它将添加。
所以,为了向我的集合添加重复值,我重写了equals(),它总是返回false,但Set仍然不允许重复值?You
hashCode
方法总是返回零。查看Math.random()
的范围
第二,您不重写您添加的元素的equals
和hashCode
。实际上,您添加了一个字符串
。要使事情正常工作,您必须实现一个类并向您添加该类的实例HashSet
。实现的类需要重写equals
和hashSet
方法,而不是主类
第三,正如评论中所说,你不应该做你正在做的事情。你真正想要的是一个
ArrayList
。通过以这种方式实现equals
和hashCode
方法,基本契约被打破。您hashCode
方法始终返回零。查看Math.random()
的范围
第二,您不重写您添加的元素的equals
和hashCode
。实际上,您添加了一个字符串
。要使事情正常工作,您必须实现一个类并向您添加该类的实例HashSet
。实现的类需要重写equals
和hashSet
方法,而不是主类
第三,正如评论中所说,你不应该做你正在做的事情。你真正想要的是一个
ArrayList
。通过以这种方式实现equals
和hashCode
方法,基本契约被打破。我假设您希望集合中的对象包含重复项(如果只是出于好奇,请继续阅读,否则请选择其他集合。可能会有帮助)
让我更正一下:
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);
}
公共类DupSet{
私有集mySet=newhashset();
//实现添加、删除和调整大小
}
公共类MyNeverEqualClass实现了可比较的{
私有静态int stupidHash=0;
私有整数;
公共MyNeverEqualClass(int num){
this.num=num;
}
@凌驾
公共int比较(MyNeverEqualClass其他){
double rnd=Math.random()*3+1
回报率(rnd>1.5)?1:-1;
}
@凌驾
公共布尔等于(MyNeverEqualClass其他){
返回false;
}
@凌驾
公共int hashCode(){
返回stupidHash++;
}
}
公共静态void main(字符串[]args){
MyNeverEqualClass a=新的MyNeverEqualClass(1);
MyNeverEqualClass b=新的MyNeverEqualClass(1);
DupSet set=新的DupSet();
增加(a);
增加(b);
}
我假设您希望集合中的对象包含重复的对象(如果只是出于好奇,请继续阅读,否则请选择其他集合。可能会有帮助)
让我更正一下:
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);
}
公共类DupSet{
私有集mySet=newhashset();
//实现添加、删除和调整大小
}
公共类MyNeverEqualClass实现了可比较的{
私有静态int stupidHash=0;
私有整数;
公共MyNeverEqualClass(int num){
this.num=num;
}
@凌驾
公共int比较(MyNeverEqualClass其他){
double rnd=Math.random()*3+1
回报率(rnd>1.5)?1:-1;
}
@凌驾
公共布尔等于(MyNeverEqualClass其他){
返回false;
}
@凌驾
公共int hashCode(){
返回stupidHash++;
}
}
公共静态void main(字符串[]args){
MyNeverEqualClass a=新的MyNeverEqualClass(1);
MyNeverEqualClass b=新的MyNeverEqualClass(1);
DupSet set=新的DupSet();
增加(a);
增加(b);
}
我阅读了源代码,从中我能够理解它是如何工作的
所以我需要一些帮助
首先
集合是定义良好且不同的对象的集合
因此,不存在添加重复值的问题。但是,如果您对理解java如何实现/实现这个约束感兴趣,那么您可以开始挖掘源代码 HashSet由HashMap支持,这意味着它将添加、删除等操作委托给
HashMap
代码>然后
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
(存储哈希映射在结构上被修改的次数),检查是否需要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
。从而防止添加重复值
我阅读了源代码,从中我能够理解它是如何工作的
所以我需要一些帮助
首先
集合是定义良好且不同的对象的集合
因此,不存在添加重复值的问题。但是,如果您对理解java如何实现/实现这个约束感兴趣,那么您可以开始挖掘源代码 HashSet由HashMap支持,这意味着它将添加、删除等操作委托给
HashMap
代码>然后
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
调用,这反过来调用HashMap#put