为什么我的HashSet不允许我添加两个相同的实例,如果他们的equals()说他们是假的?

Dan*_*lan 2 java equals set hashset

文件HashSet.add

如果指定的元素尚不存在,则将其添加到此集合中.更正式地,如果此集合不包含元素e2(e == null?e2 == null:e.equals(e2)),则将指定元素e添加到此集合.如果此set已包含该元素,则调用将保持set不变并返回false.

由于我的代码将返回false e.equals(e2),我希望它允许我添加两次相同的实例.但该集只包含我的实例一次.有人可以解释原因吗?

package com.sandbox;

import java.util.HashSet;
import java.util.Set;

public class Sandbox {

    public static void main(String[] args) {
        Set<A> as = new HashSet<A>();
        A oneInstance = new A();
        System.out.println(oneInstance.equals(oneInstance));    //this prints false
        as.add(oneInstance);
        as.add(oneInstance);
        System.out.println(as.size());  //this prints 1, I'd expect it to print 2 since the System.out printed false
    }

    private static class A {
        private Integer key;

        @Override
        public boolean equals(Object o) {
            if (!(o instanceof A)) {
                return false;
            }

            A a = (A) o;

            if (this.key == null || a.key == null) {
                return false;   //the key is null, it should return false
            }

            if (key != null ? !key.equals(a.key) : a.key != null) {
                return false;
            }

            return true;
        }

        @Override
        public int hashCode() {
            return key != null ? key.hashCode() : 0;
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

jta*_*orn 11

HashSet(实际上是HashMap)有一个"优化",它在调用equals()方法之前检查对象引用相等性.由于您将相同的实例放入两次,即使equals()方法不一致,它们也被视为相等.

来自HashMap.put()的相关行:

        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
Run Code Online (Sandbox Code Playgroud)

  • @JackStraw - 这有什么改变?复制引用不会使它不是同一个实例. (2认同)