2014-04-08 11 views
15

Ich habe folgendes Java6 und Java8 Code zu erstellen:Java8 Streams mit einer Liste von Objekten aus einem anderen

List<ObjectType1> lst1 = // a list of ObjectType1 objects 
List<ObjectType2> lst2 = // a list of ObjectType1 objects, same size of lst1 

List<ObjectType3> lst3 = new ArrayLis<ObjectType3>(lst1.size()); 
for(int i=0; i < lst1.size(); i++){ 
    lst3.add(new ObjectType3(lst1.get(i).getAVal(), lst2.get(i).getAnotherVal())); 
} 

Gibt es eine Möglichkeit in Java8 die vorherigen in einer prägnanten Art und Weise unter Verwendung von Lambda zu behandeln?

+1

Können Sie den eigentlichen Konstruktor von 'ObjectType3' bereitstellen? – skiwi

+1

Warum Streams hier verwenden? Ihre vorhandene Schleife funktioniert gut und ein Stream wird _less_ lesbar – fge

+0

@fge ich weiß. Ich möchte eine Single-Line-Lösung. Zur Lesbarkeit ist es meiner Meinung nach nur eine Frage der Übung. Ich kann die gegebene Lösung im Handumdrehen verstehen. Danke, dass du darauf hingewiesen hast! –

Antwort

26

Ein Stream ist an eine gegebene iterable/Collection gebunden, so dass Sie nicht wirklich zwei Sammlungen parallel "iterieren" können.

Eine Problemumgehung wäre, einen Strom von Indizes zu erstellen, aber dann verbessert es sich nicht notwendigerweise über die for-Schleife. Der Stream-Version könnte wie folgt aussehen:

List<ObjectType3> lst3 = IntStream.range(0, lst1.size()) 
     .mapToObj(i -> new ObjectType3(lst1.get(i).getAVal(), lst2.get(i).getAnotherVal())) 
     .collect(toList()); 
+3

@mat_boy es ist nicht wirklich kürzer als das, was Sie vorher hatten. Es ist sicher schlau, aber ich würde es nicht als Verbesserung betrachten. Java8 lehnt eine klassische for-Schleife nicht ab :) –

+0

@JoeriHendrickx Sicher, aber ich kann den Rückgabewert in einer einzelnen Zeile zuweisen. Ich weiß, es ist nicht wichtig, aber ich bevorzuge diesen Ansatz. –

+0

@JoeriHendrickx Wenn Sie 'IntStream.range (0, lst1.size()) .parallel()' schreiben, können Sie Ihre Ausführungszeit beschleunigen! Das ist ein guter Punkt, nicht wahr? :) –

5

Sie könnten eine Methode erstellen, die zwei Sammlungen in eine neue Sammlung verwandelt, wie folgt aus:

public <T, U, R> Collection<R> singleCollectionOf(final Collection<T> collectionA, final Collection<U> collectionB, final Supplier<Collection<R>> supplier, final BiFunction<T, U, R> mapper) { 
    if (Objects.requireNonNull(collectionA).size() != Objects.requireNonNull(collectionB).size()) { 
     throw new IllegalArgumentException(); 
    } 
    Objects.requireNonNull(supplier); 
    Objects.requireNonNull(mapper); 
    Iterator<T> iteratorA = collectionA.iterator(); 
    Iterator<U> iteratorB = collectionB.iterator(); 
    Collection<R> returnCollection = supplier.get(); 
    while (iteratorA.hasNext() && iteratorB.hasNext()) { 
     returnCollection.add(mapper.apply(iteratorA.next(), iteratorB.next())); 
    } 
    return returnCollection; 
} 

Der wichtige Teil hier ist, dass es die erhaltene Karte wird iteratorA.next() und iteratorB.next() in ein neues Objekt.

Es wird wie folgt aufgerufen:

List<Integer> list1 = IntStream.range(0, 10).boxed().collect(Collectors.toList()); 
List<Integer> list2 = IntStream.range(0, 10).map(n -> n * n + 1).boxed().collect(Collectors.toList()); 
singleCollectionOf(list1, list2, ArrayList::new, Pair::new).stream().forEach(System.out::println); 

In Ihrem Beispiel wäre es:

List<ObjectType3> lst3 = singleCollectionOf(lst1, lst2, ArrayList::new, ObjectType3::new); 

Wo zum Beispiel Pair::new ist eine Abkürzung für die lamdda (t, u) -> new Pair(t, u).

0

Ich habe keine Möglichkeit gefunden, 1 Stream zu einem anderen zu aktualisieren, jedoch habe ich eine ähnliche Leistung mit einer Map erreicht. :)

Map<Integer, String> result = new HashMap<>(); 
    for(int index = 100; index > 0; index--){ 
     result.put(index, String.valueOf(index)); 
    } 
    result.keySet().stream() 
      .filter(key -> key%3 == 0) 
      .sorted() 
      .forEach(key -> result.put(key, "Fizz")); 

    result.keySet().stream() 
      .filter(key -> key%5 == 0) 
      .sorted() 
      .forEach(key -> result.put(key, "Buzz")); 

    result.keySet().stream() 
      .filter(key -> key%3 == 0 && key%5 == 0) 
      .sorted() 
      .forEach(key -> result.put(key, "FizzBuzz")); 

    result.keySet().stream().forEach(key -> System.out.println(result.get(key))); 
+0

Diese Antwort ist vollständig unser Ziel! –

+0

Scheint der Problembeschreibung zu entsprechen: "Verwenden von Java8 Streams zum Erstellen einer Liste von Objekten aus einem anderen" Eine Karte kann als 2 Listen von Objekten definiert werden, mit einer 1 zu 1 Zuordnung von Domäne zu Bereich. Bei der Programmierung dreht sich alles um kreative Lösungen. –

+0

In meinem Beispiel verwende ich List not Map. Das sind zwei verschiedene Schnittstellen. Wie gesagt, ich brauchte Listen. –

Verwandte Themen