Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是否可以在HashSet中输入重复值?_Java_Set_Hashcode_Hashset - Fatal编程技术网

Java 是否可以在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

我试图通过修改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(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