为什么 java class WeakReference 不覆盖 hashcode 和 equals

why java class WeakReference does not override hashcode and equals

我期待 WeakReference class 覆盖像这样的 hashCode 和 equals 方法

class WeakReference<T>{
  T ref;

  int hashCode(){
    return ref.hashCode();
  }

  boolean equals(Object o){
    return ref.equals(o);
  }
}

这样我就可以直接使用 We WeakReference 作为哈希映射中的键,例如

Person p1 = new Person("p1");
WeakReference<Person> wr = new WeakReference<Person>(p1);

map.put(wr, "some value object");

但是当我测试时我发现 hashCode 和 equals 没有被覆盖

Person p1 = new Person("p1");
WeakReference<Person> wr = new WeakReference<Person>(p1);
WeakReference<Person> wr2 = new WeakReference<Person>(p1);

System.out.println(wr.hashCode()); // prints x
System.out.println(wr2.hashCode()); // prints y

System.out.println(wr.equals(wr2)); // prints false

在 WeakReference 中没有覆盖 hashCode 和 equals 的任何具体原因 class?

Map(或 Set 的元素)上的任何键的一个重要方面是,一旦将其添加到集合中,它就必须是不可变的(或至少不能更改)。更改密钥具有未定义的行为,这种行为极不可能起作用。

由于 GC 的执行,弱引用可以随时更改,即以您无法控制的方式更改,这使得 equals/hashCode 不适合使用这些的一般集合。

I was trying to make MyWeakConcurrentHashMap

一个简单的方法是使用一组 WeakHashMap。例如32个分区。使用 hashCode() 来确定使用哪个 WeakHashMap。这样你就可以让一个线程同时访问每个单独的 WeakHashMap(最好的情况)

随着并发性的提高,您可以增加分区数。

似乎 WeakHashMap 使用 Entry 扩展了 WeakReference
并覆盖 hashCodeequals
你可以看看它们的实现。

  /**
     * The entries in this hash table extend WeakReference, using its main ref
     * field as the key.
     */
    private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
        V value;
        final int hash;
        Entry<K,V> next;

        /**
         * Creates new entry.
         */
        Entry(Object key, V value,
              ReferenceQueue<Object> queue,
              int hash, Entry<K,V> next) {
            super(key, queue);
            this.value = value;
            this.hash  = hash;
            this.next  = next;
        }

        @SuppressWarnings("unchecked")
        public K getKey() {
            return (K) WeakHashMap.unmaskNull(get());
        }

        public V getValue() {
            return value;
        }

        public V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }

        public boolean equals(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
            K k1 = getKey();
            Object k2 = e.getKey();
            if (k1 == k2 || (k1 != null && k1.equals(k2))) {
                V v1 = getValue();
                Object v2 = e.getValue();
                if (v1 == v2 || (v1 != null && v1.equals(v2)))
                    return true;
            }
            return false;
        }

        public int hashCode() {
            K k = getKey();
            V v = getValue();
            return Objects.hashCode(k) ^ Objects.hashCode(v);
        }

        public String toString() {
            return getKey() + "=" + getValue();
        }
    }