Можно ли ввести повторяющееся значение в HashSet?

Я пытаюсь добавить повторяющиеся значения в HashSet, изменив методы hashCode() и equals()()?

Я пробовал ниже код

public class dupSet {
    static Set set= new HashSet();
    @Override
    public int hashCode() {
        return (int) (100*Math.random());
    }
    @Override
    public boolean equals(Object obj) {
        return false;
    }
    public static void main(String[] args) throws ParseException {
        set.add("a");
        set.add("b");
        set.add("a");
      System.out.println(set);
    }

}

Насколько я понимаю, если для двух дубликатов «a» HashSet сначала получит hashCode(), чтобы получить правильное ведро, а затем проверит значение equals(), если equals возвращает true, то он не добавит, но если он вернет false, то он добавит. Итак, для добавления повторяющегося значения в мой набор я переопределяю equals(), который всегда возвращает false, но все же set не допускает повторяющихся значений?


person Gautam Savaliya    schedule 05.10.2014    source источник
comment
Да, если вы неправильно переопределили метод equals.   -  person Athiruban    schedule 05.10.2014
comment
Я пытаюсь добавить повторяющиеся значения в HashSet.. ПОЧЕМУ?!   -  person Maroun    schedule 05.10.2014
comment
Что ты переопределяешь? Каково объявление класса, содержащего опубликованный вами код? Это подкласс HashSet?   -  person Eran    schedule 05.10.2014
comment
Набор — это коллекция, которая специально разработана для предотвращения дублирования. Вы используете его, когда не хотите дубликатов. Итак, почему вы решили использовать Set, если ваша цель — разрешить дубликаты? Это бессмысленно.   -  person JB Nizet    schedule 05.10.2014
comment
@MarounMaroun: просто для проверки того, как работает Hashset и как он обрабатывает повторяющиеся значения?   -  person Gautam Savaliya    schedule 05.10.2014
comment
@GautamSavaliya, почему тогда вы не читаете его исходный код?   -  person JB Nizet    schedule 05.10.2014
comment
@JBNizet: я знаю, что цель Set не в том, чтобы разрешить дубликаты, но что, если я хочу добавить, переопределив свойство по умолчанию   -  person Gautam Savaliya    schedule 05.10.2014
comment
@JBNizet: я прочитал исходный код, и из него я могу понять, как он работает, поэтому мне нужна помощь.   -  person Gautam Savaliya    schedule 05.10.2014
comment
Почему вы используете Set, если хотите, чтобы он содержал дубликаты? Почему бы вам не использовать List вместо этого?   -  person msrd0    schedule 05.10.2014


Ответы (3)


Ваш метод hashCode всегда возвращает ноль. Посмотрите на диапазон Math.random().

Во-вторых, вы не переопределяете equals и hashCode добавляемых вами элементов. Вы фактически добавляете String. Чтобы все заработало, вы должны реализовать класс и добавить к себе экземпляры этого класса HashSet. Реализованный класс должен переопределить методы equals и hashSet, а не основной класс.

В-третьих, как указано в комментариях, вы не должны делать то, что делаете. То, что вы действительно хотите, это ArrayList. При реализации методов equals и hashCode таким образом нарушается фундаментальный контракт.

person Hannes    schedule 05.10.2014

Я прочитал исходный код и понял, как он работает, поэтому мне нужна помощь

Прежде всего

Набор — это набор четко определенных и отдельных объектов.


Таким образом, не возникает вопроса о добавлении повторяющихся значений. Но если вам интересно понять, как java достигает/реализует это ограничение, вы можете начать копаться в исходном коде.

HashSet поддерживается HashMap, что означает, что он делегирует такие операции, как добавление, удаление и т. Д., HashMap. Теперь, когда вы вызываете set.add("a");, затем

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

вызывается, который, в свою очередь, вызывает HashMap#put

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

Метод put сначала вычисляет хеш-код объекта, используя

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

Как только hashCode вычисляется, он вызывает

final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict)

внутри этого метода он помещает значение, потому что это условие

if ((p = tab[i = (n - 1) & hash]) == null)

истинно, а затем увеличивает modCount (в котором хранится количество структурных изменений HashMap), проверяет, нужно ли нам resize карту, а затем вызывает afterNodeInsertion и возвращает null


Теперь, когда вы вызываете set.add("b");, снова запускается та же логика, но на этот раз условие внутри метода final V putVal

if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))

выполняется, и в связи с этим код

if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }

обнаруживает существующее сопоставление и, таким образом, возвращает oldValue . Следовательно, предотвращение добавления повторяющегося значения.

person sol4me    schedule 05.10.2014

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

Позвольте мне внести некоторые исправления:

public class DupSet<E extends Comparable<E>>{
 private Set<E> mySet = new HashSet<>();

 //Implement add, remove and size
}

public class MyNeverEqualClass implements Comparable<MyNeverEqualClass>{
  private static int stupidHash = 0;
  private int num;

  public MyNeverEqualClass(int num){
   this.num = num;
  }

  @Override
  public int compareTo(MyNeverEqualClass other){
   double rnd = Math.random()*3 + 1
   return (rnd > 1.5)? 1:-1;
  }

  @Override
  public boolean equals(MyNeverEqualClass other){
   return false;
  }

  @Override
  public int hashCode(){
   return stupidHash++;
  }
 }

 public static void main(String[] args){
  MyNeverEqualClass a = new MyNeverEqualClass(1);
  MyNeverEqualClass b = new MyNeverEqualClass(1);
  DupSet<MyNeverEqualClass> set = new DupSet<>();
  set.add(a);
  set.add(b);
 }
person Muli Yulzary    schedule 05.10.2014