Ответ 1
В случае HashMap
он заменяет старое значение новым.
В случае HashSet
элемент не вставлен.
Пожалуйста, рассмотрите приведенный ниже код:
HashSet hs = new HashSet();
hs.add("hi"); -- (1)
hs.add("hi"); -- (2)
hs.size()
даст 1, поскольку HashSet
не позволяет дублировать, так что будет сохранен только один элемент.
Я хочу знать, добавим ли мы повторяющийся элемент, заменим ли он предыдущий элемент или просто не добавим его?
Кроме того, что произойдет с помощью HashMap
для одного и того же случая?
В случае HashMap
он заменяет старое значение новым.
В случае HashSet
элемент не вставлен.
Первое, что вам нужно знать, это то, что HashSet
действует как Set
, что означает, что вы добавляете свой объект непосредственно в HashSet
и не можете содержать дубликаты. Вы просто добавляете свое значение непосредственно в HashSet
.
Однако HashMap
- это тип Map
. Это означает, что каждый раз, когда вы добавляете запись, вы добавляете пару ключ-значение.
В HashMap
вы можете иметь повторяющиеся значения, но не дублировать ключи. В HashMap
новая запись заменит старую. Самая последняя запись будет в HashMap
.
Понимание связи между HashMap и HashSet:
Помните, что HashMap
не может иметь дубликаты ключей. За сценой HashSet
используется HashMap
.
Когда вы пытаетесь добавить какой-либо объект в HashSet
, эта запись фактически сохраняется как ключ в HashMap
- тот же HashMap
, который используется за сценой HashSet
. Поскольку для этого базового HashMap
требуется пара ключ-значение, для нас создается фиктивное значение.
Теперь, когда вы пытаетесь вставить другой дублирующий объект в тот же HashSet
, он снова попытается вставить его в качестве ключа в HashMap
, лежащего под ним. Однако HashMap
не поддерживает дубликаты. Следовательно, HashSet
по-прежнему будет иметь только одно значение этого типа. В качестве побочного примечания для каждого повторяющегося ключа, поскольку значение, сгенерированное для нашей записи в HashSet, представляет собой случайное/фиктивное значение, ключ вообще не заменяется. он будет проигнорирован как удаление ключа и добавление обратно одного и того же ключа (значение фиктивного значения одинаково) не будет иметь никакого смысла.
Резюме:
HashMap
позволяет дублировать values
, но не keys
.
HashSet
не может содержать дубликатов.
Чтобы воспроизвести, успешно ли завершено добавление объекта, вы можете проверить значение boolean
, возвращаемое при вызове .add()
, и посмотреть, возвращает ли он true
или false
. Если он вернул true
, он был вставлен.
docs довольно понятны: HashSet.add
не заменяет:
Добавляет указанный элемент к этому набору, если он еще не присутствует. Более формально добавляет указанный элемент e к этому набору, если этот набор не содержит элемента e2, такого, что (e == null? E2 == null: e.equals(e2)). Если этот набор уже содержит элемент, вызов оставляет его неизменным и возвращает false.
Но HashMap.put
заменит:
Если в карте ранее содержалось отображение для ключа, старое значение заменяется.
Это случай HashSet, он НЕ заменяет его.
Из документов:
http://docs.oracle.com/javase/6/docs/api/java/util/HashSet.html#add(E)
"Добавляет указанный элемент к этому набору, если он еще не присутствует. Более формально добавляет указанный элемент e к этому набору, если этот набор не содержит элемента e2, такого, что (e == null? e2 == null: e.equals(e2)). Если это множество уже содержит элемент, вызов оставляет неизменным и возвращает false."
Исправьте меня, если я ошибаюсь, но то, что вы получаете, это то, что со строками "Привет" == "Привет" не всегда получается правдой (потому что они не обязательно являются одним и тем же объектом).
Причина, по которой вы получаете ответ от 1, объясняется тем, что JVM будет, если это возможно, повторно использовать объекты строк. В этом случае JVM повторно использует строковый объект и, таким образом, перезаписывает элемент в Hashmap/Hashset.
Но вам не гарантировано такое поведение (потому что это может быть другой строковый объект с таким же значением "Привет" ). Поведение, которое вы видите, связано только с оптимизацией JVM.
Сначала вам нужно проверить метод put на карте Hash, поскольку HashSet резервную копию HashMap
Говорить по-другому: когда вы вставляете пару ключ-значение в HashMap, где ключ уже существует (в смысле hashvalue() дает одно и то же значение und equal(), это правда, но оба объекта все равно могут отличаться несколькими способами), ключ не заменяется, но значение перезаписывается. Ключ используется только для получения значения hashvalue() и нахождения значения в таблице с ним. Так как HashSet использует ключи HashMap и устанавливает произвольные значения, которые на самом деле не имеют значения (для пользователя), в результате элементы Elements of Set также не заменяются.
В HashMap в основном содержится запись, в которой впоследствии содержатся ключи (Object) и Value (Object).Internally HashSet - это HashMap, а HashMap заменяет значения, поскольку некоторые из вас уже указывали... но действительно ли это заменяет ключи? Нет. и это трюк здесь. HashMap сохраняет свое значение как ключ в базовом HashMap, а значение - просто фиктивный объект. Поэтому, если вы пытаетесь повторно установить такое же значение в HashMap (ключ в базовой карте). Он просто заменяет фиктивное значение, а не ключ (значение для HashSet).
Посмотрите приведенный ниже код для класса HashSet:
public boolean [Подробнее...] добавить (E e) {
return map.put(e, PRESENT)==null;
}
Здесь e - значение для HashSet, но ключ для базовой карты. и ключ никогда не заменяется. Надеюсь, что смогу устранить путаницу.