Простой ответ - создать HashSet
и добавить каждый узел к набору при первом его обнаружении.
Единственный случай, когда это не сработает, это если вы перегружены hashCode()
и equals(Object)
для класса узла для реализации равенства на основе содержимого узла (или чего-либо еще).Тогда вам нужно:
- использовать класс
IdentityHashMap
, который использует ==
и System.identityHashcode
вместо equals(Object)
и hashCode()
, или - построитьхэшируй себя, используя свой собственный вид идентичности объекта.
Разве ява-объекты не являются ссылками на места в памяти?
Да и нет.Да, ссылка представлена адресом памяти (в большинстве JVM).Проблема в том, что 1) вы не можете получить адрес, и 2) он может измениться, когда GC перемещает объект.Это означает, что вы не можете использовать адрес объекта в качестве хеш-кода.
Метод identityHashCode
решает эту проблему, возвращая значение, которое изначально на основе адреса памяти.Если затем вы снова вызовете identityHashCode
для того же объекта, вы гарантированно получите то же значение, что и раньше ... даже если объект был перемещен.
Интересно, сколько проблемСтолкновения были бы, если так ..
Значения хеша, полученные методом identityHashCode
, могут конфликтовать.(То есть два различных объекта могут иметь одинаковое значение хэш-кода идентификатора.) Все, что использует эти значения, должно иметь дело с этим.(Стандартные классы HashSet
и IdentityHashMap
заботятся об этих коллизиях ... если вы решили их использовать.)