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

Java—两个哈希集是否会随着时间的推移发生类似的更改?

  •  1
  • Marciano  · 技术社区  · 6 年前

    我已经研究了不同的问题,但这些问题通常涉及一致性或排序,而我对同时包含相同元素的两个哈希集的排序感兴趣。

    我想创建一个包含整数的哈希集。随着时间的推移,我将把大小为3的哈希集放在这个更大的哈希集中,我想看看新创建的哈希集是否已经包含在这个更大的哈希集中。

    现在我的问题是,它是否总能找到重复项,或者具有相同元素的两个哈希集的顺序是否会不同?

    我很矛盾,因为它们使用相同的hashcode()函数,但这是否意味着它们总是相同的?

    HashSet<HashSet<Integer>> test = new HashSet<>();
    HashSet<Integer> one = new HashSet<>();
    one.add(1);
    one.add(2);
    one.add(5);
    test.add(one);
    HashSet<Integer> two = new HashSet<>();
    two.add(5);
    two.add(1);
    two.add(2);
    //Some other stuff that runs over time
    System.out.println(test.contains(two));
    

    上面的代码试图说明我的意思,这是否总是返回true?(请记住,我可能会用相同的元素初始化另一个哈希集,然后重试contains)

    3 回复  |  直到 6 年前
        1
  •  3
  •   Community Marks    4 年前

    是的,以上总是返回true。 Set s没有顺序,当你测试两个 设置 s彼此相等,则检查它们是否具有相同的元素。秩序没有意义。

    要详细说明, test.contains(two) 将返回true,如果仅当 test 包含具有相同 hashCode() two 等于 (根据 equals 方法)。

    两套 s1 s2 具有相同元素的 hashCode() s1.equals(s2) 返回true。

    这是合同要求的 等于 hashCode 设置 接口:

    等于

    将指定的对象与此集合进行相等性比较。如果指定的对象也是一个集合,两个集合的大小相同,并且指定集合的每个成员都包含在此集合中(或等效地,此集合的每个成员都包含在指定集合中),则返回true。此定义确保equals方法在set接口的不同实现中正常工作。

    哈希代码

    返回此集合的哈希代码值。集合的哈希代码定义为集合中元素的哈希代码之和,其中空元素的哈希代码定义为零。 这确保了s1。等于(s2)意味着s1。hashCode()=s2。任意两组s1和s2的hashCode() ,按照标的物总合同的要求。哈希代码。

    正如你所见, one 甚至不必使用相同的 设置 接口,以便 测验包含(两个) 返回true。它们必须包含相同的元素。

        2
  •  0
  •   GhostCat    6 年前

    这个 钥匙 集合的属性是关于 唯一性 钥匙数量。

    默认情况下, 插入顺序 根本没关系。

    A. 链接的 LinkedHashSet向您保证 什么时候 迭代时,元素的顺序总是相同的(用于插入它们的顺序)。但即便如此,在比较这些集合时,仍然只是关于它们的内容,而不是 插入顺序 部分

    换句话说:无论什么(默认)实现 Set 在您使用的接口中,应该始终看到一致的行为。当然,您可以自由地实现自己的集合 违反 那个合同,但好吧,违反合同会导致违反合同,也就是臭虫。

        3
  •  -1
  •   Nyamiou The Galeanthrope    6 年前

    You can look for yourself ,这是开放源代码:

    public boolean equals(Object o) {
        if (o == this)
            return true;
    
        if (!(o instanceof Set))
            return false;
        Collection<?> c = (Collection<?>) o;
        if (c.size() != size())
            return false;
        try {
            return containsAll(c);
        } catch (ClassCastException unused)   {
            return false;
        } catch (NullPointerException unused) {
            return false;
        }
    }
    
    public int hashCode() {
        int h = 0;
        Iterator<E> i = iterator();
        while (i.hasNext()) {
            E obj = i.next();
            if (obj != null)
                h += obj.hashCode();
        }
        return h;
    }
    

    您可以很容易地看到,hashcode将是元素的hashcode之和,因此它不受任何顺序的影响,并且等于use containsAll(…)所以这里的顺序也不重要。