Възможно ли е да въведете дублирана стойност в 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);
    }

}

Според моето разбиране, ако за два дубликата на "а" HashSet първо ще получи hashCode(), за да получи подходяща кофа и след това ще провери стойността на equals(), ако е равно връща true, тогава няма да добави, но ако върне false, тогава ще добави. Така че за добавяне на дублираща се стойност към моя Set аз замествам 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
Комплектът е колекция, която е специално проектирана да предотвратява дублиране. Използвате го, когато не искате дубликати. И така, защо избирате да използвате набор, ако целта ви е да позволите дубликати? Това няма смисъл.   -  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