441 Stimmen

Abrufen eines Elements aus einer Menge

Warum ist die Set eine Operation anbieten, um ein Element zu erhalten, das gleich einem anderen Element ist?

Set<Foo> set = ...;
...
Foo foo = new Foo(1, 2, 3);
Foo bar = set.get(foo);   // get the Foo element from the Set that equals foo

Ich kann fragen, ob die Set ein Element enthält, das gleich ist mit bar Warum kann ich dieses Element nicht bekommen? :(

Zur Klarstellung: Die equals wird überschrieben, aber es wird nur eines der Felder überprüft, nicht alle. Also zwei Foo Objekte, die als gleich angesehen werden, können tatsächlich unterschiedliche Werte haben, deshalb kann ich nicht einfach foo .

14voto

Jesse Glick Punkte 23182

Wenn Ihr Set tatsächlich ein NavigableSet<Foo> (wie zum Beispiel ein TreeSet ), und Foo implements Comparable<Foo> können Sie verwenden

Foo bar = set.floor(foo); // or .ceiling
if (foo.equals(bar)) {
    // use bar…
}

(Dank an @eliran-malkas Kommentar für den Hinweis.)

10voto

Jason M Punkte 79

Warum?

Es scheint, dass Set eine nützliche Rolle spielt, indem es ein Mittel zum Vergleich bietet. Es ist darauf ausgelegt, keine doppelten Elemente zu speichern.

Wenn man aufgrund dieser Absicht/des Designs einen Verweis auf das gespeicherte Objekt erhält() und es dann verändert, ist es möglich, dass die Designabsichten von Set durchkreuzt werden und ein unerwartetes Verhalten hervorrufen können.

Von der JavaDocs

Große Vorsicht ist geboten, wenn veränderbare Objekte als Mengenelemente verwendet werden. Das Verhalten einer Menge ist nicht spezifiziert, wenn der Wert eines Objekts auf eine Weise geändert wird, die sich auf Gleichheitsvergleiche auswirkt, während das Objekt ein Element der Menge ist.

Wie?

Nach der Einführung von Streams kann man nun Folgendes tun

mySet.stream()
.filter(object -> object.property.equals(myProperty))
.findFirst().get();

8voto

To Kra Punkte 2979

Set in Liste umwandeln, und dann mit get Methode der Liste

Set<Foo> set = ...;
List<Foo> list = new ArrayList<Foo>(set);
Foo obj = list.get(0);

6voto

Xymon Punkte 225
Object objectToGet = ...
Map<Object, Object> map = new HashMap<Object, Object>(set.size());
for (Object o : set) {
    map.put(o, o);
}
Object objectFromSet = map.get(objectToGet);

Wenn Sie nur eine Abfrage durchführen, ist dies nicht sehr leistungsfähig, da Sie alle Elemente in einer Schleife abrufen, aber wenn Sie mehrere Abfragen für eine große Menge durchführen, werden Sie den Unterschied bemerken.

4voto

rghome Punkte 7901

Wenn Sie sich die ersten Zeilen der Implementierung von java.util.HashSet werden Sie sehen:

public class HashSet<E>
    ....
    private transient HashMap<E,Object> map;

Así que HashSet verwendet HashMap interaktiv, d.h. wenn Sie nur eine HashMap direkt eingeben und den gleichen Wert wie den Schlüssel und den Wert verwenden, erhalten Sie den gewünschten Effekt und sparen sich etwas Speicherplatz.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X