Есть два пути. Первым будет линейный поиск .
Поскольку референт действительно пропал, и вы не можете вычислить hashCode
на нем, вы можете искать Reference
с помощью ==
, по all записей в Map
. В опубликованном примере вы можете добавить несколько строк, например:
WeakReference<Referent> weak = new WeakReference<>(ref, q);
// <--- this
System.out.println(weak);
ref = null;
while (weak.get() != null) {
System.out.println("not yet");
System.gc();
}
Reference<? extends Referent> reference = q.poll();
// <---- and this
System.out.println(reference);
. Они обе будут печатать одну и ту же вещь, что вполне логично. Таким образом, теоретически, WeakHashMap
может взять reference
, который он получил (что на самом деле Entry
), и пройти его внутренний массив, пока не будет найдено совпадение.
Очевидно, что это будет медленно.
Второй подход - это тот, который WeakHashMap
фактически принимает . Когда Entry
создается впервые, он вычисляет hashCode
и помещает его в локальное поле:
/**
* 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;
}
В этот момент он знает Key
, поэтому он может вычислить hashCode
, Когда позже вызывается expungeStaleEntries
:
private void expungeStaleEntries() {
for (Object x; (x = queue.poll()) != null; ) {
synchronized (queue) {
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>) x;
int i = indexFor(e.hash, table.length);
Он уже знает hashCode
, так как он был вычислен до этого. Он не знает Key
, но в этом также нет необходимости.
Это поможет найти корзину, в которой будет находиться эта запись, но на самом деле найти указанную запись c, она может используйте ==
только для самой записи. поскольку Key
ушло, equals
невозможно, но это не имеет значения.