So erstellen Sie eine neue Liste mit einer Eigenschaft eines Objekts, das sich in einer anderen Liste befindet

79

Stellen Sie sich vor, ich habe eine Liste bestimmter Objekte:

List<Student>

Und ich muss eine andere Liste erstellen, einschließlich der idsvon Studentsin der obigen Liste:

List<Integer>

Ist es möglich, eine Schleife zu vermeiden, indem Apache-Sammlungen oder Guaven verwendet werden ?

Welche Methoden sollten für meinen Fall nützlich sein?

Javatar
quelle
Hey, ich habe es gerade gefunden: stackoverflow.com/questions/737244/…
Javatar
Jons Antwort ist ziemlich cool, aber wenn man es sich ansieht, verwendet es auch eine Schleife. Jede beliebige Lösung wird eine Schleife verwenden - obwohl es nicht sichtbar sein könnte zu Ihnen, aber intern wird es
hage
Jemand muss eine Schleife anwenden, um dies zu erreichen. entweder Sie oder eine Bibliothek, die Sie verwenden können.
Sudmong
Eigentlich passt Jon's Antwort nicht zu meiner Situation, da ich keine for-Schleife verwenden möchte. Ich denke, es gibt irgendwo einen bequemeren Weg, aber ich warte darauf, dass ich ihn finde :)
Javatar

Antworten:

172

Java 8 Vorgehensweise: -

List<Integer> idList = students.stream().map(Student::getId).collect(Collectors.toList());
Kaushik
quelle
1
Was ist, wenn ich eine Liste von Tupeln möchte? So etwas wie [(Id, Name), (Id, Name)].
Khazana
Nicht alle 1.8-Funktionen werden für alle Android-APIs unterstützt. Insbesondere wird java.util.stream erst nach API 24 unterstützt.
The Black Horse
41

Mit Guava können Sie Funktionen wie - verwenden

private enum StudentToId implements Function<Student, Integer> {
        INSTANCE;

        @Override
        public Integer apply(Student input) {
            return input.getId();
        }
    }

und Sie können diese Funktion verwenden, um die Liste der Schüler in IDs wie - zu konvertieren.

Lists.transform(studentList, StudentToId.INSTANCE);

Sicherlich wird es eine Schleife ausführen, um alle IDs zu extrahieren, aber denken Sie daran, dass Guavenmethoden die Ansicht zurückgeben und die Funktion nur angewendet wird, wenn Sie versuchen, über List<Integer>
die Schleife zu iterieren. Wenn Sie nicht iterieren, wird die Schleife niemals angewendet .

Hinweis: Denken Sie daran , das der Ansicht ist , und wenn Sie mehrere Male zu wiederholen wollen wird es besser sein , den Inhalt in einem anderen zu kopieren , List<Integer>wie

ImmutableList.copyOf(Iterables.transform(students, StudentToId.INSTANCE));
Premraj
quelle
Ich finde es unelegant, eine Funktion separat definieren zu müssen. Ich denke, dies kann auch anonym und in einem Schritt erfolgen
Marc
Wie extrahiert man String-Mitglieder (Float usw.) aus der Liste?
September
22

Vielen Dank an Premraj für die alternative coole Option, die positiv bewertet wurde.

Ich habe Apache CollectionUtils und BeanUtils verwendet. Dementsprechend bin ich mit der Leistung des folgenden Codes zufrieden:

List<Long> idList = (List<Long>) CollectionUtils.collect(objectList, 
                                    new BeanToPropertyValueTransformer("id"));

Es ist erwähnenswert, dass ich die Leistung von Guave ( Premraj bereitgestellt) und collectionUtils, die ich oben verwendet habe, vergleichen und die schnellere entscheiden werde.

Javatar
quelle
3
Ich werde Guave Apache-Sammlungen vorziehen, unabhängig von der Leistung aus Gründen wie - moderner, generischer, verwendet keine Reflexion für Transformationen usw. Insgesamt ist Guave weitaus moderner als Apache-Sammlungen - lesen Sie hier
Premraj
1
Ja, aber eigentlich scheint es mir keine gute Idee zu sein, die Verwendung durch eine obligatorische zusätzliche Aufzählungsdeklaration für jeden Objekttyp, den ich transformieren möchte, einzuschränken.
Javatar
Nun, es hängt von Ihrem Design ab. Sie können die Schnittstelle angeben lassen, Identifiablewelche getId()Methode definiert wird, und dann können Sie dieses einzelne Enum-Singleton-Muster verwenden, um die ID häufig zu extrahieren.
Premraj
2
Guave ist definitiv effizienter als Bean Utils, da die spätere Reflexionen verwendet ..
Ravi
2
Die Verwendung des Eigenschaftsnamens als Zeichenfolge im Konstruktor new BeanToPropertyValueTransformer ("id") ist etwas, das ich definitiv vermeiden möchte. Refactoring wird schwer! Aber ich suche nach einer Lösung, um dies zu umgehen. In der Zwischenzeit werde ich mich für die Guava-Lösung entscheiden, ausführlich, aber sicher.
Redochka
7

Java 8 Lambda-Ausdruckslösung:

List<Integer> iDList = students.stream().map((student) -> student.getId()).collect(Collectors.toList());
Opster Elasticsearch Pro-Vijay
quelle
Wenn Java <1.8, verwenden Sie Apache CollectionUtils. Beispiel: Collection <String> firstnames = CollectionUtils.collect (Benutzerliste, TransformerUtils.invokerTransformer ("getFirstname"));
a_subscriber
5

Wenn jemand nach ein paar Jahren hierher kommt:

List<String> stringProperty = (List<String>) CollectionUtils.collect(listOfBeans, TransformerUtils.invokerTransformer("getProperty"));
Jonathan Perrotta
quelle
Und du hast mich gerade gerettet :)
Behrad3d
-5

Es ist mathematisch unmöglich, dies ohne eine Schleife zu tun. Um eine Zuordnung F eines diskreten Wertesatzes zu einem anderen diskreten Wertesatz zu erstellen, muss F für jedes Element in der Ursprungsmenge arbeiten. (Dazu ist grundsätzlich eine Schleife erforderlich.)

Davon abgesehen:

Warum brauchen Sie eine neue Liste? Sie könnten sich dem Problem, das Sie lösen, falsch nähern.

Wenn Sie eine Liste von haben Student, sind Sie beim Durchlaufen dieser Liste nur ein oder zwei Schritte davon entfernt, die ID-Nummern der Schüler zu durchlaufen.

for(Student s : list)
{
    int current_id = s.getID();
    // Do something with current_id
}

Wenn Sie ein anderes Problem haben, kommentieren / aktualisieren Sie die Frage und wir werden versuchen, Ihnen zu helfen.

Zéychin
quelle
Zunächst vielen Dank für Ihre Antwort. Es ist jedoch dramatisch, dass Sie sagten, die Notwendigkeit einer neuen Liste sei falsch. Weil es auf die Kapazität und Reichweite des Bedarfs ankommt. Daher ist Ihr Ansatz der falsche Weg :) Wiederum ist meine Erwähnung von "Fähigkeit, das ohne Schleife zu erreichen" ein bequemerer Weg, um Code nicht unlesbar und leistungsschwach zu machen. Wie auch immer, ich habe bereits einen Weg gefunden, es zu erreichen, und werde es ein wenig teilen.
Javatar
Ich habe nicht gesagt , dass es ist der falsche Weg, aber es könnte der falsche Weg sein, abhängig von dem Problem , das Sie versuchen zu lösen.
Zéychin