Angenommen, ich habe eine Liste von Objekten mit zwei Feldern field1
und field2
beide vom Typ String.
Wie bekomme ich eine Liste aller field1
Werte, ohne über die Liste iterieren zu müssen, wenn es überhaupt möglich ist?
Benutzer1343585
Angenommen, ich habe eine Liste von Objekten mit zwei Feldern field1
und field2
beide vom Typ String.
Wie bekomme ich eine Liste aller field1
Werte, ohne über die Liste iterieren zu müssen, wenn es überhaupt möglich ist?
Glücklicherweise können Sie dies mit tun Java 8 – Streams
Angenommen, Sie haben eine Entität mit dem Namen IhreEntität
public class YourEntity {
private String field1;
private String field2;
public YourEntity(String field1, String field2) {
this.field1 = field1;
this.field2 = field2;
}
public void setField1(String field1) {
this.field1 = field1;
}
public void setField2(String field2) {
this.field2 = field2;
}
public String getField1() {
return field1;
}
public String getField2() {
return field2;
}
}
Deklarieren Sie Ihre Liste von IhreEntität mit:
List<YourEntity> entities = Arrays.asList(new YourEntity("text1", "text2"), new YourEntity("text3", "text4"));
Sie können die Liste von extrahieren Feld1 auf einen Schlag so:
import java.util.stream.Collectors;
List<String> field1List = entities.stream().map(YourEntity::getField1).collect(Collectors.toList());
Oder auf diese Weise
import java.util.stream.Collectors;
List<String> field1List = entities.stream().map(urEntity -> urEntity.getField1()).collect(Collectors.toList());
Sie können alle Artikel auch mit Java 8 drucken 🙂
field1List.forEach(System.out::println);
Ausgabe
text1
text3
Wie kann dies für eine beliebige Anzahl von Feldern in einer Entitätsklasse erreicht werden? Angenommen, ich schreibe eine gemeinsame Methode, um dies für eine beliebige Anzahl von Feldern in einer einzelnen Entitätsklasse oder einer beliebigen Entitätsklasse zu erreichen, die ich als Argument in der Methode sende.
– Hart
20. Juli 2018 um 8:59 Uhr
Euclides Mulémbwe
Versuche dies:
List<Entity> entities = getEntities();
List<Integer> listIntegerEntities = Lambda.extract(entities, Lambda.on(Entity.class).getFielf1());
LambdaJ ermöglicht den Zugriff auf Sammlungen ohne explizite Schleifen. Anstatt also mehr Codezeilen zu haben, um die Liste selbst zu durchlaufen, lassen Sie LambdaJ dies tun.
Diese Antwort sollte auf jeden Fall mit einer kurzen Beschreibung dessen aktualisiert werden, was hier verwendet wird (LambdaJ?).
– tonedzwiedz
12. Juni 2012 um 13:04 Uhr
Ein Objekt ist eine Referenz auf eine Speicheradresse. Dann sind die Felder dieser Objekte andere Verweise auf andere Speicheradressen. Daher ist eine Liste von Objekten eine Liste von Referenzen. Daher ist es für die Liste unmöglich, direkt auf die Objektfelder (Referenzen, die durch die Referenzen gegeben sind) zuzugreifen. Die kurze Antwort ist nein.
Hinweis: Auf jeden Fall finden Sie eine API, die das tut, was Sie wollen, sie läuft immer noch im Inneren.
Unbedingt beachten. Sie könnten eine Sammlung implementieren, die beim Einfügen Elemente zu einer Liste hinzufügt, die Sie basierend auf Suchkriterien indizieren, und dann direkt die Liste selbst zurückgibt. Auf diese Weise wäre das Einfügen etwas ineffizient, aber das Abrufen würde es ermöglichen, das zu tun, was das OP will.
– Haylem
12. Juni 2012 um 13:19 Uhr
Das stimmt, aber eine solche Sammlung wäre sehr spezifisch für die Art der Objekte, die sie enthält, anstatt generisch zu sein.
– dounyy
12. Juni 2012 um 13:25 Uhr
teilweise, ja, um nicht vollständig “fixiert” zu sein, müssten Sie Begrenzungsschnittstellen oder Reflektion verwenden, also müssen Sie den Typen, die Sie einfügen können, entweder eine leichte Starrheit auferlegen, oder eine Auswirkung auf die Leistung und Komplexität des Indexers. Aber das ist durchaus machbar. Tatsächlich wäre ich nicht überrascht, wenn einige der Bibliotheken und Spracherweiterungen, die implementiert wurden, um Abfragefunktionen für Java-Sammlungen und zusammengesetzte Objekte bereitzustellen, etwas in der Art des zweiten Ansatzes verwenden würden.
– Haylem
12. Juni 2012 um 14:25 Uhr
Ich stimme hier nicht zu; Es stimmt, dass eine Liste logischerweise die Liste der Referenzen sein muss, aber eine Liste ist nur eine Schnittstelle – wenn sie das Richtige zurückgibt, muss sie keinen Hintergrundspeicher haben. Siehe meine Antwort unten für eine Version, die keine Schleife macht und die Anforderungen erfüllt.
– Benutzer295691
21. Januar 2014 um 21:55 Uhr
Haylem
… ob sich deine Fragen darauf beziehen avoiding iterating over the collection
entweder:
Meinst du konkret:
Siehe unten für Lösungen und Optionen.
Wenn es die erste ist, dann schauen Sie sich Google Guava, LambdaJ, FunctionalJava oder andere Bibliotheken an, die grundlegende funktionale Konstrukte implementieren und es Ihnen ermöglichen, in wenigen ausdrucksstarken Aufrufen zu tun, was Sie wollen. Denken Sie jedoch daran, dass diese das tun, was auf der Dose steht: Sie filtern, sammeln oder transformieren eine Sammlung und durchlaufen dazu ihre Elemente.
Zum Beispiel:
Set<String> strings = buildSetStrings();
Collection<String> filteredStrings =
Collections2.filter(strings, Predicates.containsPattern("^J"));
Array<Integer> a = array(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42);
Array<Integer> b = a.filter(even);
List<Integer> biggerThan3 = filter(greaterThan(3), asList(1, 2, 3, 4, 5));
Wenn es der zweite ist, Dies ist so wie es ist nicht möglich, außer wenn Sie alles von Anfang an so gestaltet haben Ihre Objekte sollten von einer benutzerdefinierten Sammlungsklasse verwaltet werden, die Ihre Objekte basierend auf ihren Feldwerten beim Einfügen indizieren würde.
Es würde sie in Buckets halten, die durch diesen Wert indexiert sind, damit Sie sie als Liste abrufen oder bei Bedarf festlegen können.
Wie in den Kommentaren unter dounyys Antwort erwähnt, würde das Entwerfen einer solchen benutzerdefinierten Sammlung wahrscheinlich Auswirkungen auf die API der Elemente haben, die es akzeptieren würde (höchstwahrscheinlich durch Definieren einer Superschnittstelle zur Verwendung für Elementtypen) oder eine ziemlich komplizierte Implementierung erfordern Mitglieder dynamisch aufzulösen (höchstwahrscheinlich mithilfe von Reflektion), wenn Sie jemals wollten, dass diese Auflistung generisch ist.
Weder Java als Sprache noch JDK-Bibliotheken machen noch nicht das, was Sie wollen. Sie können entweder verwenden LambdaJ oder warten Sie auf Java 8, von dem erwartet wird, dass es Lambda-Ausdrücke enthält.
Wie würde das die Iteration vermeiden? Lambda J würde es immer noch für Sie tun. ansonsten könnten Sie dafür bereits Google Guava oder LambdaJ oder FunctionalJava oder viele andere verwenden. Aber sie durchlaufen natürlich alle die Strukturen.
– Haylem
12. Juni 2012 um 13:04 Uhr
Du hast Recht, @haylem. Offensichtlich muss jemand die Sammlung durchlaufen. Keine Möglichkeit, es zu vermeiden. Wenn Closures in Java eingeführt werden, werden sie hinter den Kulissen dasselbe tun. Die von Ihnen erwähnten Tools helfen uns nur, kürzeren Code zu schreiben.
– AlexR
13. Juni 2012 um 6:21 Uhr
Benutzer295691
Alte Frage, aber ich bin darauf gestoßen, als ich nach einer ähnlichen Lösung gesucht habe.
Sie können die implementieren List<String>
Schnittstelle, ohne eine ausgearbeitete zu erstellen ArrayList<String>
und wird daher nicht über das übergeordnete Objekt iteriert.
final List<Entity> entities = getEntities()
final List<String> field1 = new AbstractList() {
public String get(int index) {
return entities.get(index).getField1();
}
public int size() {
return entities.size();
}
}
Dadurch erhalten Sie eine Liste, ohne das übergeordnete Objekt zu durchlaufen.
Wahlfreier Zugriff auf die abgeleitete List<String>
genauso teuer wie der wahlfreie Zugriff auf den Basiswert List<Entity>
; wenn Sie eine Implementierung von verwenden List<Entity>
das keinen schnellen wahlfreien Zugriff bietet, müssen Sie möglicherweise durch ein paar Hürden springen (dh mehr Methoden von implementieren List<String>
. Dies sollte jedoch für 99% der Fälle funktionieren, in denen Sie einen leichten Adapter benötigen.
Wie würde das die Iteration vermeiden? Lambda J würde es immer noch für Sie tun. ansonsten könnten Sie dafür bereits Google Guava oder LambdaJ oder FunctionalJava oder viele andere verwenden. Aber sie durchlaufen natürlich alle die Strukturen.
– Haylem
12. Juni 2012 um 13:04 Uhr
Du hast Recht, @haylem. Offensichtlich muss jemand die Sammlung durchlaufen. Keine Möglichkeit, es zu vermeiden. Wenn Closures in Java eingeführt werden, werden sie hinter den Kulissen dasselbe tun. Die von Ihnen erwähnten Tools helfen uns nur, kürzeren Code zu schreiben.
– AlexR
13. Juni 2012 um 6:21 Uhr
manasBVSS
Das Objekt sei von der folgenden Klasse.
public class Bike {
String bikeModel;
Int price;
}
Und jetzt gibt es eine Fahrradliste namens bikeList vom Typ List
Also wollen wir jetzt eine Liste der Fahrradmodelle aller Fahrräder in der obigen Liste.
bikeList.map{ Bike b -> b.bikeModel }.toCollection(arrayListOf())
gibt eine Array-Liste des ersten Felds aller Fahrradobjekte in der Fahrradliste zurück
Nein, gibt es im Normalfall nicht. Oder hast du mehr Details?
– kan
12. Juni 2012 um 12:59 Uhr
“ohne durchlaufen zu müssen”, Überhaupt nicht, denke ich.
– Umesh Aawte
12. Juni 2012 um 13:00 Uhr
without having to iterate through the list
Sie meinen, Sie würden die Liste nicht durchlaufen, oder sogar eine Bibliothek nicht? Wollen Sie im Grunde nur etwas, das sich einfach eingeben lässt, oder wirklich O(1)-Zugriff auf eine Teilmenge von Objekten basierend auf Bedingungen? Es sind 2 völlig unterschiedliche Fragen.– Haylem
12. Juni 2012 um 13:13 Uhr