2015-09-19 16 views
11

Durch das Schreiben von Anwendungen in Java gibt es viele Anwendungsfälle für java.util.Collection. Da java.util.stream.Stream mit Java 8 eingeführt wurde, kam ich über einige Anwendungsfälle, in denen es schwierig ist zu entscheiden, was zu verwenden ist.Entscheidung zwischen der Verwendung eines Stream oder einer Schleife

Zum Beispiel: Sie werden einige util-Methoden schreiben.

public static List<?> filterHashToList(int hash, Collection<?> toFilter) { 
    return toFilter.stream() 
     .filter((Object o) -> hash == o.hashCode()) 
     .collect(Collectors.toCollection(LinkedList::new)); 
} 

Was es so zu schreiben:

public static List<?> filterHashToList(int hash, Collection<?> toFilter) { 
    List<Object> result = new LinkedList<>(); 

    for(Object o : toFilter) { 
     if(hash == o.hashCode()) { 
      result.add(o); 
     } 
    } 

    return result; 
} 

Beiden Methoden zum gleichen Ergebnis führen würden. java.util.stream.Stream und java.util.stream.Collector sind Schnittstellen, daher kann die Implementierung auch variieren, wenn ich benutzerdefinierte Streams und Collectors verwende.

Ich denke, es gibt viele Implementierungen da draußen mit dem altmodischen Loop-Weg.

Also, ist es möglich, zu beantworten, was zu verwenden, Stream oder Loop, von Use-Case? Und wenn ja, müssen alle Implementierungen gegebenenfalls aktualisiert werden?

Oder sollte ich beide Möglichkeiten durch die Implementierung von util-Methoden bieten? Oder sollte ich auch eine mthed bereitstellen, die den Stream nach dem Filterprozess zurückgibt, damit Sie bei Bedarf auch mit dem Stream arbeiten können?

+0

Sie können wirklich einfache Parallelität mit Streams haben, sie sind kompakter (manche würden "lesbarer" sagen) und haben weitere Vorteile, wenn Ihre Streams tatsächliche "Streams" sind (etwas fließt dynamisch ein - nicht auf Basis eines feste Sammlung wie hier). Aber in Ihrem speziellen Fall denke ich, dass Sie in beide Richtungen gehen könnten. – mastov

+0

Also können wir das verkürzen zu: Streams sollen bevorzugt werden, aber in einfachen Anwendungsfällen ist beides in Ordnung? – narranoid

+3

Ich würde zwei einfache Regeln verwenden: 1. Wenn es nicht kaputt ist, repariere es nicht. 2. Verwenden Sie das, was Sie am besten lesen und pflegen können. Das heißt, Ihre beiden Beispiele geben nicht die gleiche Sache zurück: Einer gibt eine ArrayList zurück und der andere gibt eine LinkedList zurück. –

Antwort

5

Beachten Sie, dass Sie in Ihrer Implementierung Stick mit speziellen Kollektionstyp LinkedList führt, die in der Regel sehr schlechte Leistung im Vergleich zu ArrayList. Was ist, wenn der Benutzer Ihrer Methode die resultierende Liste in zufälliger Weise verwenden möchte? Wahrscheinlich benötigt der Benutzer dieser Methode ein Array, weil es an eine andere API-Methode übergeben werden soll, die ein Array akzeptiert. Manchmal muss der Benutzer nur wissen, wie viele Objekte mit gegebenem hashCode in der Eingabesammlung vorhanden sind. Daher muss keine resultierende Liste erstellt werden. Die Java-8 Art und Weise ist Strom von den Methoden zurückzukehren, nicht die Sammlungen und lassen Sie den Anrufer entscheiden, wie es zu sammeln:

public static <T> Stream<T> filterHashToList(int hash, Collection<T> toFilter) { 
    return toFilter.stream() 
     .filter(o -> hash == o.hashCode()); 
} 

und es verwenden:

filterHashToList(42, input).count(); 

Oder

filterHashToList(42, input).collect(toCollection(ArrayList::new)); 

Oder

filterHashToList(42, input).toArray(); 

Dieses wa Die Methode wird sehr einfach, Sie brauchen sie wahrscheinlich gar nicht, aber wenn Sie eine bessere Filterung/Transformation durchführen wollen, ist das in Ordnung.

Wenn Sie also die API nicht ändern und trotzdem die LinkedList zurückgeben möchten, müssen Sie die Implementierung nicht ändern. Wenn Sie jedoch den Vorteil der Verwendung der Stream-API nutzen möchten, sollten Sie den Rückgabetyp lieber in Stream ändern.

8

In Ermangelung einer geschriebenen Antwort werde ich Brian Goetz zitieren, der meine Stimmung widerspiegelt und ich verdächtige viele andere '.

Es gibt nichts Magisches an Streams oder Loops. Sie sollten den Code schreiben, der am besten lesbar, klar und wartbar ist. Beide sind akzeptabel.

0

Ich denke, das ist weitgehend abhängig von der erwarteten Größe der Sammlung und praktische Anwendung des Programms. Ersteres ist etwas effizienter, aber ich finde es weniger lesbar und es gibt immer noch Systeme, die auf Java 7 laufen (zB Google App Engine). Darüber hinaus wäre es wahrscheinlich einfacher, komplexere Filter hinzuzufügen. Wenn Effizienz jedoch das Hauptanliegen ist, würde ich mit dem ersteren gehen.

Verwandte Themen