Wie erhalte ich eine Liste bestimmter Feldwerte von Objekten, die in einer Liste gespeichert sind?

Lesezeit: 8 Minuten

Benutzeravatar von user1343585
Benutzer1343585

Angenommen, ich habe eine Liste von Objekten mit zwei Feldern field1 und field2beide 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?

  • 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

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

Benutzeravatar von Euclides Mulémbwè
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

Benutzeravatar von haylem
Haylem

Hängt davon ab…

… ob sich deine Fragen darauf beziehen avoiding iterating over the collection entweder:

  • in Bezug auf die einfache Implementierung an Meldestellen
  • oder in Bezug auf die algorithmische Komplexität.

Meinst du konkret:

  • Sie möchten kein iterierendes Konstrukt selbst eingeben (verwenden Sie einfach eine Convenience-Bibliothek),
  • oder Sie möchten tatsächlich etwas, das Elemente automatisch in O (1) zurückgibt, ohne sie verarbeiten zu müssen (und perfekten Zugriff haben)?

Siehe unten für Lösungen und Optionen.


Verwenden von Convenience-Bibliotheken

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:

  • Google Guave:

    Set<String> strings = buildSetStrings();  
    Collection<String> filteredStrings =
        Collections2.filter(strings, Predicates.containsPattern("^J"));  
    
  • Funktionales Java:

    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);
    
  • LambdaJ:

    List<Integer> biggerThan3 = filter(greaterThan(3), asList(1, 2, 3, 4, 5));
    

Perfekter Zugriff

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

Benutzeravatar von user295691
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

Benutzeravatar von manasBVSS
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

1441280cookie-checkWie erhalte ich eine Liste bestimmter Feldwerte von Objekten, die in einer Liste gespeichert sind?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy