2017-01-02 3 views
1

Gibt es einen allgemeinen besten Ansatz für var-arg Methode Signaturen in Bezug auf die Java 8 Lambda/Closure?Java-Methodensignaturen: Stream versus Collection vs. var-arg

In einer Situation, wo ein Verfahren entweder mit einem einzelnen Objekt als Parameter oder eine Sammlung von Objekten dieses Ich sehe drei Möglichkeiten zu erkennen, verwendet wird:

ist
private void optionOneVararg(String... params) { ... } 
private void optionTwoCollection(Collection<String> params) { ... } 
private void optionThreeStream(Stream<String> params) { ... } 

Die String-Klasse offensichtlich als Beispiel verwendet.

Gibt es einen allgemein gültigen "Best Practice" -Ansatz? Der Vararg-Ansatz erzeugte den schlauesten Code bis zu Java 7. Bei Streams fühlt es sich plump an.

Ich möchte in der Lage sein, die Bequemlichkeit von Lambda sowohl innerhalb der Methode als auch außerhalb zu verwenden, wo ich es nenne. Ich möchte auch den Umwicklungs-/Klebstoffcode (z. B. Collections.singletonList(element) oder Arrays.asList(element)) auf ein Minimum beschränken und vermeiden, Collection myCollection = stream.collect(...) gefolgt von myCollection.stream() zu verwenden.

+0

Was magst du an der Vararg-Option nicht? – assylias

+0

Im var-args-Thema sollten Sie sich [diese Frage] ansehen (http://stackoverflow.com/questions/766559/when-do-you-use-varargs-in-java). – Paul

+0

@assylias Wenn ich Operationen für einen Stream verwende (z. B. Filter), das Ergebnis an meine Funktion weitergebe und dann mehr Stream-Operationen für diesen Parameter verwende, benötigt das vararg-Array eine Erfassung des ersten Streams, bevor es an die Funktion übergeben werden kann . – SebastianH

Antwort

0

Dank AR.3s Antwort erkennen ich, dass die Stream als Parameter zu halten sowohl in der Leistung und der ästhetischen Aspekt überlegen:

private void callOptionThreeFromStream() { 
    List<String> foo = Arrays.asList(new String[] { "a", "b", "c" }); 
    Stream<String> stream = foo.stream(); 
    // use stream here 
    optionThreeStream(stream); 
} 
private void callOptionThreeFromObject() { 
    String bar = "a"; 
    optionThreeStream(Stream.of(bar)); //very simple conversion 
} 
private void optionThreeStream(Stream<String> params) { 
    // use the same stream (and possibly profit from optimization) 
} 

einen Vararg Parameter verwenden verursacht mehr Overhead (zumindest ästhetisch):

private void callOptionOneFromStream() { 
    List<String> foo = Arrays.asList(new String[] { "a", "b", "c" }); 
    Stream<String> stream = foo.stream(); 
    // use stream here 
    optionOneVararg(stream.toArray(String[]::new)); //still clumsy 
} 
private void callOptionOneFromObject() { 
    String bar = "a"; 
    optionOneVararg(bar); //but optimal here 
} 
private void optionOneVararg(String... params) { 
    Stream<String> stream = Stream.of(params); 
    // use the new stream on the newly created array 
} 

Und der Vollständigkeit halber:

private void callOptionTwoFromStream() { 
    List<String> foo = Arrays.asList(new String[] { "a", "b", "c" }); 
    Stream<String> stream = foo.stream(); 
    // use stream here 
    optionTwoCollection(stream.collect(Collectors.toList())); //clumsy 
} 
private void callOptionTwoFromObject() { 
    String bar = "a"; 
    optionTwoCollection(Collections.singletonList(bar)); //clumsy 
} 
private void optionTwoCollection(Collection<String> params) { 
    Stream<String> stream = params.stream(); 
    // use the new stream on the newly created collection 
} 

Meine persönliche Schlussfolgerung: Verwenden Sie Stream für private Methoden. Wenn jedoch var-arg oder Collections in öffentlichen API-Methoden beibehalten werden, sind interne technische Details möglicherweise besser ausgeblendet.

Es ist ein schönes Detail, dass Stream.of einen Var-Arg-Parameter verwendet, um Arrays und einzelne Objekte auf einmal abzudecken.

+0

'Stream.of()' Varargs werden nicht für einzelne Objekte verwendet. Die 'of()' Methode ist überladen. Siehe: http://stackoverflow.com/questions/35802272/why-overload-the-varargs-method-of-in-java-stream-interface – jaco0646

+0

Sehr guter Fang! Vielen Dank. Es ist nicht so, dass mich diese Art von Mikrooptimierung in meinem Code interessiert, aber deine Frage war eine gute Lektüre. Es gibt auch ein anderes Argument, um den Stream an die innere Funktion zu übergeben, wenn sie verfügbar ist. – SebastianH

2

Sie können immer noch die Stream API und Lambdas in der Methode verwenden, indem Sie Stream.of(String...) aufrufen. In diesem Fall können Sie die Signatur mit dem varargs halten:

private void optionVarArgs(String... params) { 
    Stream.of(params)... 
    ... 
} 
+0

Guter Hinweis. Aber was ist mit der rufenden Seite? Das sieht wirklich hässlich aus: 'stream.collect (Collectors.toList()). ToArray (neuer String [0])' – SebastianH

+2

@SebastianH 'stream.toArray (String [] :: neu)' – assylias