Why are two AtomicIntegers never equal?

前端 未结 9 2140
日久生厌
日久生厌 2020-12-01 18:02

I stumbled across the source of AtomicInteger and realized that

new AtomicInteger(0).equals(new AtomicInteger(0))

evaluates to

9条回答
  •  既然无缘
    2020-12-01 18:32

    equals is not only used for equality but also to meet its contract with hashCode, i.e. in hash collections. The only safe approach for hash collections is for mutable object not to be dependant on their contents. i.e. for mutable keys a HashMap is the same as using an IdentityMap. This way the hashCode and whether two objects are equal does not change when the keys content changes.

    So new StringBuilder().equals(new StringBuilder()) is also false.

    To compare the contents of two AtomicInteger, you need ai.get() == ai2.get() or ai.intValue() == ai2.intValue()

    Lets say that you had a mutable key where the hashCode and equals changed based on the contents.

    static class BadKey {
        int num;
        @Override
        public int hashCode() {
            return num;
        }
    
        @Override
        public boolean equals(Object obj) {
            return obj instanceof BadKey && num == ((BadKey) obj).num;
        }
    
        @Override
        public String toString() {
            return "Bad Key "+num;
        }
    }
    
    public static void main(String... args) {
        Map map = new LinkedHashMap();
        for(int i=0;i<10;i++) {
            BadKey bk1 = new BadKey();
            bk1.num = i;
            map.put(bk1, i);
            bk1.num = 0;
        }
        System.out.println(map);
    }
    

    prints

    {Bad Key 0=0, Bad Key 0=1, Bad Key 0=2, Bad Key 0=3, Bad Key 0=4, Bad Key 0=5, Bad Key 0=6, Bad Key 0=7, Bad Key 0=8, Bad Key 0=9}
    

    As you can see we now have 10 keys, all equal and with the same hashCode!

提交回复
热议问题