代码之家  ›  专栏  ›  技术社区  ›  Vivek

如何设置重复项检查?Java哈希集

  •  -2
  • Vivek  · 技术社区  · 6 年前

    对于以下代码,它输出“1”。第二个代码输出“2”,我不明白为什么会这样。是因为我正在添加相同的对象吗?我应该如何实现期望的输出2。

    import java.util.*;
    public class maptest {
    public static void main(String[] args) {
        Set<Integer[]> set = new HashSet<Integer[]>();
        Integer[] t = new Integer[2];
        t[0] = t[1] = 1;
        set.add(t);
        Integer[] t1 = new Integer[2];
        t[0] = t[1] = 0;
        set.add(t);
        System.out.println(set.size());
    
       }
    }
    

    import java.util.*;
    public class maptest {
    public static void main(String[] args) {
        Set<Integer[]> set = new HashSet<Integer[]>();
        Integer[] t = new Integer[2];
        t[0] = t[1] = 1;
        set.add(t);
        Integer[] t1 = new Integer[2];
        t1[0] = t1[1] = 1;
        set.add(t1);
        System.out.println(set.size());
    
        }
    }
    
    4 回复  |  直到 6 年前
        1
  •  3
  •   Sweeper    6 年前

    Set 实现可能需要 t.hashCode() 因为数组不会覆盖 Object.hashCode 方法,则相同的对象将具有相同的哈希代码。因此,更改数组的内容不会影响其哈希代码。要正确获取数组的哈希代码,应该调用 Arrays.hashCode .

    无论如何,你不应该把可变的东西放在集合中,所以我建议你把不可变的列表放在集合中。如果您想继续使用数组,只需创建一个新数组,就像您使用 t1 ,并将其放入集合中。

    编辑:

    对于代码2, t 是两个不同的数组,因此它们的哈希代码不同。再说一次,自从 hashCode 方法未在数组中重写。数组的内容不影响哈希代码,不管它们是否相同。

        2
  •  2
  •   NoDataFound    6 年前

    Set 只包含不同的元素(这是它的本质)。基本实施, HashSet hashCode() 首先找到一个包含值的bucket,然后 equals(Object)

    数组很简单:它们的hashCode()使用默认值,继承自 Object 等于(对象) 也和 对象 :它只检查标识,即:引用必须等于。

    定义为Java:

    public boolean equals(Object other) {
      return other == this;
    }
    

    如果你想放置不同的数组,你要么试试运气 TreeSet 以及适当实施 Comparator List 或者别的

    Set<List<Integer[]>> set = new HashSet<>();
    Integer[] t = new Integer[]{1, 1};
    set.add(Arrays.asList(t));
    Integer[] t1 = new Integer[]{1, 1};
    set.add(Arrays.asList(t1));
    System.out.println(set.size());
    

    至于在一个系统中使用的对象的可变性 或者 Map

    • 用户使用的字段 boolean equals(Object)
    • 用户使用的字段 int hashCode() 对于基于哈希的集合不应禁用( , HashMap )因为如上所述,他们是通过把物品放在桶里来运作的。如果hashCode()发生了变化,那么对象在bucket中的位置很可能也会发生变化: 将包含两次相同的引用。
    • 用户使用的字段 int compareTo(T) Comparator::compare(T,T) equals SortedSet

    如果需要,您必须首先从集合中删除项,然后对其进行变异,然后重新添加它。

        3
  •  2
  •   GBlodgett    6 年前

    您正在添加 Object Set 哪一个

    不包含重复元素。

    你只添加了一个 对象 . 你只改变它的内容的值。要明白我的意思,请尝试添加 System.out.println(set.add(t)); .

    作为 add() 方法:

    如果此集合尚未包含指定的元素,则返回true

    t1 在您的第一个代码段中是完全不相关的,因为您从未使用过它。


    在第二个代码段中,它输出两个,因为您正在添加两个 不同的 Integer[] Objects

    试着打印出 物体 要了解其工作原理:

    Integer[] t = new Integer[2];
    t[0] = t[1] = 1;
    //Before we change the values
    System.out.println(t.hashCode());
    Integer[] t1 = new Integer[2];
    t1[0] = t1[1] = 1;
    //After we change the values of t
    System.out.println(t.hashCode());
    //Hashcode of the second object
    System.out.println(t1.hashCode());
    

    输出:

    //Hashcode for t is the same before and after modifying data
    366712642
    366712642
    //Hashcode for t1 is different from t; different object
    1829164700
    
        4
  •  1
  •   John Bollinger    6 年前

    怎么 java.util.Set 检查 对于重复对象取决于实现,但根据 Set “复制”的恰当含义是 o1.equals(o2)

    HashSet 特别是基于哈希表的,它会通过计算 hashCode()

    数组不重写 哈希码() equals() ,因此它们实现实例标识,而不是值标识。因此,不管其元素的值如何,给定的数组总是具有相同的哈希代码,并且总是 等于() 只有它自己。第一个代码将同一个数组对象添加到一个集合中两次。不管元素的值是多少,它仍然是同一组。第二个代码将两个不同的数组对象添加到一个集合中。不管元素的值如何,它们都是不同的对象。

    同样要注意的是,如果您有实现值标识的可变对象,使得它们的相等性和哈希代码取决于它们的成员的值,那么在对象是