it-swarm.com.de

HashSet enthält doppelte Einträge

Ein HashSet speichert nur Werte, wenn die Methode equals angibt, dass sie gleich sind. Das ist was ich dachte.

Aber jetzt füge ich Elemente zu einem HashSet hinzu, bei dem die equals-Methode true zurückgibt und die Größe des Sets immer noch wächst? Entschuldigung ich bin verwirrt. Einige Hinweise, wo ich falsch liege, wären Nizza.

Element t1 = new Element(false, false, false, false);
Element t2 = new Element(true, true, true, true);
Element t3 = new Element(false, false, false, false);

if (t1.equals(t3))
    System.out.println("they're equal");

Set<Element> set = new HashSet<>();

set.add(t1);
set.add(t2);
set.add(t3);

System.out.println("set size: " + set.size());

in diesem Beispiel lautet meine Konsolenausgabe:

sie sind gleich
eingestellte Größe: 3

Das macht für mich keinen Sinn .. sollte die Größe nicht 2 sein?

13
tObi

Das Problem ist, dass Ihre Element-Klasse die equals- und hashCode-Methoden nicht überschrieben hat oder dass diese Implementierungen fehlerhaft sind.

Von Object#equals method javadoc:

Die equals-Methode implementiert eine Äquivalenzbeziehung für Objektreferenzen, die nicht Null sind:

  • Es ist reflexiv: Für jeden Referenzwert x, der nicht Null ist, sollte x.equals (x) den Wert true zurückgeben.
  • Es ist symmetrisch: Für alle Nicht-Null-Referenzwerte x und y sollte x.equals (y) genau dann true zurückgeben, wenn y.equals (x) true zurückgibt.
  • Es ist transitiv: Wenn für alle Nicht-Null-Referenzwerte x, y und z x.equals (y) true und y.equals (z) true zurückgibt, sollte x.equals (z) true zurückgeben. ____.] Es ist konsistent: Für alle Nicht-Null-Referenzwerte x und y geben mehrere Aufrufe von -x.equals (y) konsistent true zurück oder geben konsistent false zurück, vorausgesetzt, es werden keine Informationen geändert, die in Gleichheitsvergleichen der Objekte verwendet werden.
  • Für jeden Referenzwert x, der nicht Null ist, sollte x.equals (null) den Wert false zurückgeben.

Von Object#hashCode method javadoc:

Der allgemeine Vertrag von hashCode ist:

  • Wenn die hashCode-Methode für dasselbe Objekt mehr als einmal während der Ausführung einer Java-Anwendung aufgerufen wird, muss sie die gleiche Ganzzahl konsistent zurückgeben, vorausgesetzt, es werden keine Informationen geändert, die in Gleichheitsvergleichen für das Objekt verwendet werden. Diese Ganzzahl muss von einer Ausführung einer Anwendung zu einer anderen Ausführung derselben Anwendung nicht konsistent bleiben.
  • Wenn zwei Objekte gemäß der Methode equals (Object) gleich sind, muss das Aufrufen der hashCode-Methode für jedes der beiden Objekte dasselbe Ganzzahlergebnis ergeben.
  • Wenn zwei Objekte gemäß der equals-Methode (Java.lang.Object) ungleich sind, ist es nicht erforderlich, dass beim Aufruf der hashCode-Methode für jedes der beiden Objekte unterschiedliche Integer-Ergebnisse erzeugt werden müssen. Dem Programmierer sollte jedoch bewusst sein, dass die Erzeugung eindeutiger ganzzahliger Ergebnisse für ungleiche Objekte die Leistung von Hashtabellen verbessern kann. 

Stellen Sie sicher, dass die Implementierungen dieser Methoden diese Regeln erfüllen, und Ihre Set (unterstützt durch eine HashSet) wird wie erwartet funktionieren.

19
Luiggi Mendoza

Ihre Objekte haben unterschiedliche Hashes, so dass HashSet dann in verschiedene "Eimer" setzt.

4

Wenn Sie über eigene Modellklassen verfügen, müssen Sie einige grundlegende Funktionen ändern, wie im folgenden Beispiel beschrieben. 

Ausführungscode:

HashSet<MyModel> models = new HashSet<MyModel>();

for (int i = 1; i < 5; i++)
    models.add(new MyModel(i + "", "Name :" + i + ""));

for (int i = 3; i < 5; i++)
    models.add(new MyModel(i + "", "Name :" + i + ""));

for (Object object : models)
    System.out.println(object);

Modellklasse:

/**
 * Created by Arun
 */
public static class MyModel {

    private String id = "";
    private String name = "";

    public MyModel(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return getId();
    }

    @Override
    public boolean equals(Object obj) {
        return !super.equals(obj);
    }

    public int hashCode() {
        return getId().hashCode();
    }

}

Hoffe das hilft.

4
Arun

Ja, wir können es mit dem Objekt der Klassen implementieren, die nichtFINALsind.

HashSet prüft vor dem Hinzufügen eines Objekts nach zwei Methoden hashCode() und equals(). Zuerst wird nach der Methode hashCode() gesucht. Wenn es den Hashcode zurückgibt, der same mit dem Objekt in Set ist, wird nach dem Objekt gesucht Die equals-Methode für dieses Objekt, die intern die Referenzen für beide Objekte vergleicht, dh this.obj1==obj. Wenn dies die gleichen Referenzen sind, wird mit true ein doppelter Wert zurückgegeben. Wir können duplizieren Nicht-Final-Objekte durch Überschreiben der HashCode- und Equals-Methode. In HashCode () können Sie denselben Hashcode für die gleichen Parameter zurückgeben.

Siehe Beispiel:

public class Product {
int i;
Product(int a)
{
    this.i=a;
}
@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + i;
    return result;
}
@Override
public boolean equals(Object obj) {
    /*if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Product other = (Product) obj;
    if (i != other.i)
        return false;
    return true;*/
    return true;
}
}
`

`
import Java.util.HashSet;
import Java.util.Set;
public class Main {
public static void main(String[] args) {
    Product p1=new Product(1);
    Product p2=new Product(1);
    Product p3=new Product(1);
    Set s=new HashSet();
    s.add(p1);
    s.add(p2);
    s.add(p3);
    System.out.println(s.size());
}
}

Die Ausgabe wird 1 sein.

P.S: Ohne diese Methoden zu überschreiben, wird die Ausgabe 3 sein, da sie ihr Standardverhalten verwendet.

1
Shailesh Modi