java.util.Set
реализация удаляет повторяющиеся элементы.
Как элементы дубликатов удаляются изнутри в java.util.Set
java.util.Set
реализация удаляет повторяющиеся элементы.
Как элементы дубликатов удаляются изнутри в java.util.Set
На самом деле AFAIK из источников в большинстве реализаций Set
в java даже не проверяет, содержится ли этот элемент.
Они всегда выполняют add()
в своей внутренней структуре, которая содержит элементы набора и позволяет этому объекту обрабатывать случай дублирования.
например. HashSet
вызывает put(K,V)
во внутреннем HashMap
, который просто вставляет новый объект, перезаписывая старую запись, если дубликат.
Внимательно прочитав ваш вопрос, я предполагаю, что вы видите странное поведение с java.util.HashSet
(как правило, все по умолчанию используют).
В соответствии с контрактом java.util.Set
можно получить один и тот же объект в java.util.HashSet
в два раза:
import java.util.HashSet;
import java.util.Set;
public class SetTest
{
public static void main(String[] args)
{
MyClass myObject = new MyClass(1, "testing 1 2 3");
Set<MyClass> set = new HashSet<MyClass>();
set.add(myObject);
myObject.setHashCode(2);
set.add(myObject);
System.out.println(set.size()); // this will print 2.
}
private static class MyClass
{
private int hashCode;
private String otherField;
public MyClass(int hashCode, String otherField)
{
this.hashCode = hashCode;
this.otherField = otherField;
}
public void setHashCode(int hashCode)
{
this.hashCode = hashCode;
}
public boolean equals(Object obj)
{
return obj != null && obj.getClass().equals(getClass()) && ((MyClass)obj).otherField.equals(otherField);
}
public int hashCode()
{
return hashCode;
}
}
}
После указателя из @jitter и взгляда на источник вы можете понять, почему это произойдет.
Как и @jitter, java.util.HashSet
использует java.util.HashMap
внутренне. Когда хеш изменяется между первым и вторым, в java.util.HashMap
используется другое ведро, и объект находится в наборе дважды.
Пример кода может выглядеть немного уверенным, но я видел, как это происходит в дикой природе с доменами, где хэш создается из изменяемых полей, и метод equals не синхронизирован с этими полями.
Легкий способ узнать это - посмотреть в источнике кода, который вас интересует.
В каждом JDK включен src.zip, который содержит исходный код для общедоступных классов, поэтому вы можете просто найти источник для HashSet и посмотреть:) Я часто использую Eclipse для этого. Запустите его, создайте новый Java-проект, установите JVM как установленный JDK (если вы не используете JRE, установленный по умолчанию, который не имеет src.zip) и Ctrl-Shift-T, чтобы перейти к HashSet.
Подробнее читайте ваш вопрос:
Вы не можете добавлять дубликаты из java doc для Set.add() или вы имеете в виду addAll?:
Добавляет указанный элемент к этому набору, если он еще не присутствует (дополнительная операция). Более формально добавляет указанный элемент e к этому набору, если в наборе нет элемента e2, такого, что (e == null? E2 == null: e.equals(e2)). Если этот набор уже содержит элемент, вызов оставляет его неизменным и возвращает false. В сочетании с ограничением на конструкторы это гарантирует, что множества никогда не содержат повторяющихся элементов.