1086 Stimmen

Wie kann ich zwei Listen in Java verbinden?

Bedingungen: keine Änderung der ursprünglichen Listen; nur JDK, keine externen Bibliotheken. Bonuspunkte für einen Einzeiler oder eine JDK 1.3 Version.

Gibt es einen einfacheren Weg als:

List<String> newList = new ArrayList<String>();
newList.addAll(listOne);
newList.addAll(listTwo);

7 Stimmen

Wenn Sie tun dies ausschließlich für Iteration Zwecke siehe eine andere Frage - es gibt Google Guava und Java 8 Lösungen stackoverflow.com/questions/4896662/

0 Stimmen

Java 8-Lösung mit Utility-Methode: stackoverflow.com/a/37386846/1216775

0 Stimmen

Dies ist nur eine der vielen Unzulänglichkeiten der Java Collections API.

1092voto

Dale Emery Punkte 8391

In Java 8:

List<String> newList = Stream.concat(listOne.stream(), listTwo.stream())
                             .collect(Collectors.toList());

153 Stimmen

Mein Gott, das gibt es in Java 8? Technisch gesehen hast du wohl gewonnen, aber das ist eine verdammt lange Zeile :-)

1 Stimmen

Ich frage mich, ob das Erstellen und Durchlaufen von zwei Streams einen spürbaren Einfluss auf die Leistung hat. Ich nehme an, es sollte nicht, im Vergleich zu zwei Iteratoren erstellen.

6 Stimmen

Für Gelegenheitsleser gibt es eine kürzere Lösung, die auch Java _ Streams verwendet: stackoverflow.com/a/34090554/363573

693voto

AdamC Punkte 15701

Aus dem Stegreif kann ich ihn um eine Zeile kürzen:

List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);

196 Stimmen

Es ist zwar technisch korrekt, dass Sie ihn um eine Zeile gekürzt haben, aber die Asymmetrie stört mich. So sehr, dass ich lieber die zusätzliche Zeile "ausgeben" möchte.

17 Stimmen

Gibt es nicht ein Problem hier, wo die newList's interal Array auf die Größe von listOne initialisiert wird und dann möglicherweise erweitern müssen, wenn alle Elemente aus listTwo hinzufügen? Wäre es besser, die Größe der einzelnen Listen zu nehmen und diese für die Größe des neuen Arrays zu verwenden?

3 Stimmen

Das war die Lösung, die für mich am besten funktioniert hat. Ich habe einen Vergleich über die Leistung der verschiedenen Lösungen gemacht, die als Sieger hervorging, zusammen mit der Erstellung der leeren Liste und dann addAll() von beidem. Ich habe all jene ausprobiert, die vorschlagen, die Listen nicht zu kopieren, und das Ergebnis ist eine Menge Overhead, den wir dieses Mal nicht brauchten.

449voto

Guillermo Punkte 4033

Sie könnten die Apache-Commons-Sammlungen Bibliothek:

List<String> newList = ListUtils.union(list1, list2);

75 Stimmen

Nett, erfordert aber Apache Commons. Er hat "keine externen Bibliotheken" angegeben

128 Stimmen

@Quantum7, immer noch nützlich für andere Leute ;) Und ist Apache Commons überhaupt eine externe Bibliothek? Ich starte nichts ohne sie!

31 Stimmen

@Platinum Nein, laut der Dokumentation ist ListUtils.union genau gleich wie der Code von OP. Aber vielleicht ist es irreführend, eine SET-Operation ("Union") in einem Listenkontext zu verwenden. Ich verstehe, wie man erwarten kann, dass dadurch Duplikate oder ähnliches entfernt werden, aber es scheint, dass die Methode das nicht tut.

257voto

Mark Punkte 2577

Ein weiterer Java 8-Einzeiler:

List<String> newList = Stream.of(listOne, listTwo)
                            .flatMap(Collection::stream)
                            .collect(Collectors.toList());

Als Bonus, da Stream.of() variabel ist, können Sie beliebig viele Listen miteinander verknüpfen.

List<String> newList = Stream.of(listOne, listTwo, listThree)
                            .flatMap(Collection::stream)
                            .collect(Collectors.toList());

45 Stimmen

x -> x.stream() könnte ersetzt werden durch Collection::stream .

22 Stimmen

...oder sogar mit List::stream .

0 Stimmen

Sehr schön. Ich mag diesen Ansatz.

102voto

Kevin K Punkte 9140

Eine Ihrer Anforderungen ist es, die ursprünglichen Listen zu erhalten. Wenn Sie eine neue Liste erstellen und die addAll() verdoppeln Sie effektiv die Anzahl der Verweise auf die Objekte in Ihren Listen. Dies kann zu Speicherproblemen führen, wenn Ihre Listen sehr groß sind.

Wenn Sie das verkettete Ergebnis nicht ändern müssen, können Sie dies mit einer benutzerdefinierten Listenimplementierung vermeiden. Die benutzerdefinierte Implementierungsklasse besteht natürlich aus mehr als einer Zeile... aber ihre Verwendung ist kurz und bündig.

CompositeUnmodifiableList.java:

public class CompositeUnmodifiableList<E> extends AbstractList<E> {

    private final List<? extends E> list1;
    private final List<? extends E> list2;

    public CompositeUnmodifiableList(List<? extends E> list1, List<? extends E> list2) {
        this.list1 = list1;
        this.list2 = list2;
    }

    @Override
    public E get(int index) {
        if (index < list1.size()) {
            return list1.get(index);
        }
        return list2.get(index-list1.size());
    }

    @Override
    public int size() {
        return list1.size() + list2.size();
    }
}

Verwendung:

List<String> newList = new CompositeUnmodifiableList<String>(listOne,listTwo);

13 Stimmen

Dies ist eine praktikable Lösung, aber beachten Sie, dass sich der Inhalt dieser Liste ändert, wenn sich die zugrundeliegenden Listenobjekte (list1, list2) ändern. Möglicherweise können Sie eine Instanz der CompositeUnmodifiableList nicht ändern selbst aber wenn Sie einen Verweis auf die Originallisten bekommen können, dann schon. Auch für diejenigen, die damit nicht vertraut sind: der letzte Modifikator wirkt sich nur auf die Referenz auf das Listenobjekt selbst kann sich nicht ändern, aber es ist trotzdem möglich, dass sich der Inhalt der Liste ändert!

3 Stimmen

@jwj alles sehr gute Punkte, danke. Der Klassenname ist wahrscheinlich erklärungsbedürftig. Ich sehe diese Klasse so, dass sie etwas sehr ähnliches macht wie die Collections.unmodifiableList() Methode, die eine Liste umhüllt, um sie unveränderbar zu machen. CompositeUnmodifiableList macht das Gleiche, nur dass es zwei Listen umschließt und eine verkettete Ansicht liefert. Alle Punkte, die Sie über CompositeUnmodifiableList gelten auch für Collections.unmodifiableList() auch.

2 Stimmen

Der Konstruktor kann List<? extends E>

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