2016-09-20 1 views
1

Ich bin Anfänger von Java 8 und heute habe ich gerade mit meinem allerersten lambda Ausdruck begonnen. Ich habe ein String Array, wollen Werte vor und nach dem Sortieren drucken. Unten ist mein Code, jetzt gibt es stream has already operated upon or closed Ausnahme, weil ich die forEach zweimal auf friendsStream verwendet habe.Stream - Druckwerte vor und nach der Sortierung

import java.util.stream.Stream; 
class FirstLambda { 
    public static void main(String [] args){ 
     String [] friends = new String [] {"C","A","B","D"}; 

     Stream<String> friendsStream = Stream.of(friends); 

     System.out.println("My Friends:-"); 
     printStream(friendsStream); 

     System.out.println("My Friends (after sort):- "); 
     Stream<String> sortedFriends = friendsStream.sorted((String m,String n) -> m.compareTo(n)); 
     printStream(sortedFriends); 
    } 

    private static void printStream(Stream<String> stream) { 
     stream.forEach(s->System.out.println(s)); 
    } 
} 

Meine Frage ist, was ist der einfachste oder beste Weg, um mein Problem zu lösen? Das bedeutet, dass die Zeichenfolgenwerte vor und nach dem Sortieren unter Verwendung von java 8Stream (dh Lambda)

+2

Sie nur 'friendsStream.sorted verwenden können()' ohne Lambda zu sortieren, da durch Standardmäßig wird diese 'compareTo' Methode verwendet. Die Lösung besteht darin, zwei verschiedene "Stream" -Objekte zu verwenden. – 4castle

+0

Ich stimme zu.Wie aber drucke ich Werte vor dem Sortieren und nach dem Sortieren? – Sridhar

+1

@Sridhar * Die Lösung ist, zwei verschiedene Stream-Objekte zu verwenden. * –

Antwort

3

Wenn Sie fragen, „Was ist die einfachste oder beste Weg ist, um mein Problem zu lösen“, dann die Antwort ist, dass Sie überhaupt keinen Stream brauchen:

Beachten Sie, dass das gleiche mit der Collection-API funktioniert:

List<String> friends = Arrays.asList("C", "A", "B", "D"); 
System.out.println("My Friends: "+friends); 
friends.sort(Comparator.naturalOrder()); 
System.out.println("My Friends (after sort): "+friends); 

Wenn Sie die Stream-API einbinden möchten, gibt es mehrere Ansätze. Die einfachste:

String[] friends = {"C", "A", "B", "D"}; 
System.out.println("My Friends: "); 
Arrays.stream(friends).forEachOrdered(System.out::println); 
System.out.println("My Friends (after sort): "); 
Arrays.stream(friends).sorted().forEachOrdered(System.out::println); 

anzumerken, dass Arrays.stream der bevorzugte Weg ist, um einen Strom für ein bestehendes Array, die für int[], long[] und double[] Arbeit wird auch zu konstruieren, während Stream.of die kanonische Weise ist einen Strom von der Konstruktion mit gegebenen Argumente, unter Verwendung der Varargs Funktion, z Stream.of("C", "A", "B", "D").

Wir können dies für die nächste Variante verwenden, einen einzelnen Stream mit und in den Strom späht:

Stream.of("C", "A", "B", "D") 
     .peek(System.out::println) 
     .sorted() 
     .forEachOrdered(System.out::println); 

Aber beachten Sie, dass peek ist in erster Linie für das Debuggen der Stream-Verarbeitung, wie es zu sehen Elemente ermöglicht, wie sie verarbeitet werden, .

Aber wenn Sie die Stream-API verstehen wollen, sollten Sie vermeiden forEach oder forEachOrdered verwenden, da alle Operationen forEach/forEachOrdered am Ende wird nur eine alternative Art und Weise des Schreibens eine Schleife und mehr als oft, eine kompliziertere Art und Weise enthalten.

Anbetracht dessen, dass die tatsächliche bestimmungsgemäßen Betrieb ist eine Zeichenfolge zu komponieren zu drucken, eine anspruchsvollere Nutzung wäre:

String[] friends = {"C", "A", "B", "D"}; 
System.out.println("My Friends: " 
    +Arrays.stream(friends).collect(Collectors.joining(", "))); 
System.out.println("My Friends (after sort): " 
    +Arrays.stream(friends).sorted().collect(Collectors.joining(", "))); 
+0

Ich mag diesen Single-Stream mit Spähen .. awesome – Sridhar

+3

Aber wie gesagt, das ist vor allem für herauszufinden, wie Elemente verarbeitet werden, was gut ist lerne (so siehst du, dass 'sort' die Verarbeitung aller Quellelemente erzwingt, bevor das Terminal' forEachOrdered' sie verarbeitet, so wie die meisten anderen Zwischenoperationen nicht funktionieren, zB probiere mit 'filter' anstelle von' sort'), und Es ist gut zum Debuggen, aber nicht die richtige Lösung für den Produktionscode. – Holger

+1

Was ich an der Verwendung von 'Collectors.joining' nicht mag, ist, dass es vor dem Drucken eine einzelne potentiell große Zeichenfolge im Speicher erstellt. Es ist also nicht so effizient, wie es beim direkten Ausdruck von "System.out" sein könnte. – 4castle

2

gedruckt werden. Jede Stream kann nur eine Terminaloperation haben. forEach ist ein Terminal-Vorgang, so dass Sie jedes Mal, wenn Sie printStream verwenden möchten, ein separates Objekt Stream verwenden müssen.

Verwenden Sie eine Stream vor der Art, und eine andere Stream nach der Art:

import java.util.stream.Stream; 
import java.util.Arrays; 

public class FirstLambda { 
    public static void main(String [] args) { 
     String[] friends = new String[] {"C","A","B","D"}; 

     System.out.println("My Friends:-"); 
     printStream(Arrays.stream(friends)); 

     System.out.println("My Friends (after sort):- "); 
     printStream(Arrays.stream(friends).sorted()); 
    } 

    private static void printStream(Stream<?> stream) { 
     stream.forEach(System.out::println); 
    } 
} 

Ideone Demo