Повторяющиеся элементы в java.util.Set - PullRequest
11 голосов
/ 29 октября 2009

java.util.Set Реализации удаляют дубликаты элементов.

Как дубликаты удаляются изнутри в java.util.Set ??

Ответы [ 4 ]

14 голосов
/ 29 октября 2009

На самом деле AFAIK из исходных кодов большинства Set реализаций в java даже не проверяет, содержится ли элемент уже.

Они просто всегда выполняют add() на своей внутренней структуре, которая содержит заданные элементы и позволяет этому объекту обрабатывать случай дублирования.

например. HashSet вызывает put(K,V) на внутреннем HashMap, который просто вставляет новый объект, перезаписывая старую запись в случае дублирования.

11 голосов
/ 29 октября 2009

Читая немного вашего вопроса, я предполагаю, что вы видите странное поведение с 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 внутри. Когда хэш изменяется между первым и вторым add , в java.util.HashMap используется другой сегмент, и объект находится в наборе дважды.

Пример кода может показаться немного надуманным, но я видел, как это происходит в дикой природе с классами домена, где хеш создается из изменяемых полей, а метод equals не синхронизируется с этими полями.

2 голосов
/ 29 октября 2009

Простой способ выяснить это - найти в коде интересующий вас код.

В каждый JDK включен src.zip, который содержит исходный код для открытых классов, так что вы можете просто найти исходный код для HashSet и посмотреть :) Я часто использую Eclipse для этого. Запустите его, создайте новый проект Java, установите JVM в качестве установленного JDK (если вы не используете системный JRE по умолчанию, у которого нет src.zip), и Ctrl-Shift-T, чтобы перейти к HashSet.

0 голосов
/ 29 октября 2009

Читайте ваш вопрос более подробно:

Вы не можете добавлять дубликаты из документа Java для Set.add () или вы имеете в виду addAll ?:

Добавляет указанный элемент к этому набору, если он еще не существует (необязательная операция). Более формально, добавляет указанный элемент e в этот набор, если набор не содержит элемент e2, такой что (e == null? E2 == null: e.equals (e2)). Если этот набор уже содержит элемент, вызов оставляет набор неизменным и возвращает false. В сочетании с ограничением на конструкторы это гарантирует, что наборы никогда не будут содержать повторяющиеся элементы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...