Вы действительно не должны использовать хеш-код в качестве ключа на вашей карте.Хеш-код класса не предназначен для того, чтобы обязательно гарантировать, что он не будет одинаковым для любых двух неравных экземпляров этого класса.Действительно, ваш метод хеш-кода может определенно создать один и тот же хеш-код для двух неравных экземпляров.Вам нужно для реализации equals
на MyClass
, чтобы проверить, что два экземпляра MyClass
равны на основе равенства String
и int
, которые они содержат.Я также рекомендовал бы сделать поля s
и i
final
, чтобы обеспечить более надежную гарантию неизменности каждого экземпляра MyClass
, если вы собираетесь использовать его таким образом.
Кроме того, я думаю, что вам на самом деле здесь нужен интернер .... то есть что-то, что гарантирует, что вы когда-либо сохраните не более 1 экземпляра данного MyClass
в памяти навремя.Правильным решением этого является Map<MyClass, MyClass>
... точнее ConcurrentMap<MyClass, MyClass>
, если есть вероятность вызова getOrCreateMyClass
из нескольких потоков.Теперь вам нужно создать новый экземпляр MyClass
, чтобы проверить кэш при использовании этого подхода, но на самом деле это неизбежно ... и это не имеет большого значения, потому что MyClass
легко создать.
Guava имеет кое-что, что делает всю работу за вас здесь: интерфейс Interner и соответствующий Interners фабричный / служебный класс.Вот как вы можете использовать его для реализации getOrCreateMyClass
:
private static final Interner<MyClass> interner = Interners.newStrongInterner();
public static MyClass getOrCreateMyClass(String s, int i) {
return interner.intern(new MyClass(s, i));
}
Обратите внимание, что использование сильного интернера, как и вашего примера кода, сохранит каждый MyClass
, который он хранит в памяти, пока интернер находится впамяти, независимо от того, имеет ли что-либо еще в программе ссылку на данный экземпляр.Если вместо этого вы используете newWeakInterner
, когда в вашей программе больше ничего не используется с данным экземпляром MyClass
, этот экземпляр будет иметь право на сборку мусора, что поможет вам не тратить память на экземпляры, которые вам не нужны.
Если вы решите сделать это самостоятельно, вы захотите использовать ConcurrentMap
кеш и использовать putIfAbsent
.Вы можете взглянуть на реализацию сильного интерна в Guava для справки, я думаю ... подход слабых ссылок намного сложнее.