2016-05-16 16 views
0

Jemand fragte mich in einem Interview, ob wir Streaming-Betrieb in der Hauptmethode schreiben sollten.Java 8 Stream in der Hauptmethode

Macht es einen Unterschied?

Zum Beispiel:

class Athlete { 

    private String name; 
    private int id; 

    public Athlete(String name,int id) { 
    this.name = name; 
    this.id = id; 
    } 
} 

public class Trial { 

    public static void main(String[] args) { 
    List<Athlete> list = new ArrayList<>(); 
    list.add(new Athlete("John", 1)); 
    list.add(new Athlete("Jim", 2)); 
    list.add(new Athlete("Jojo", 3)); 

    list.stream().forEach(System.out::print); // or any other any stream operation 
    } 
} 

So bin ich einfach nur neugierig zu wissen, ob es einen Unterschied ... Denn jetzt macht, das einzige, was ich weiß, ist, dass, sobald der Strom verbraucht wird, kann sie nicht verzehrt werden nochmal.

Beeinflusst es den Speicher oder erstellt Pufferspeicher in der JVM für das Streaming?

Wenn ja? Warum sollte dies nicht in der Hauptmethode verwendet werden?

+1

Ich glaube nicht, dass es irgendwelche Streams gibt, die sie in Bezug auf Hauptmethode/Thread besonders machen. Welche Argumente Sie auch für oder gegen Argumente verwenden können, könnte auch für die Verwendung von Iteratoren oder anderen Loops verwendet werden. –

+0

Hallo Danke für Ihre Antwort ..... es ist nur ein Beispiel .... Ich bin nicht Fragen über Schleifen hier ... Ich frage über schreiben Stream-Vorgang in unserer Hauptmethode .... danke –

Antwort

4

Die Frage, ob "wir Streaming-Operation in der Hauptmethode schreiben sollten" ist eine geladene Frage. Das erste, was es impliziert, ist die Annahme, dass es etwas Besonderes an der Methode main gab. Unabhängig davon, über welche Operationen wir sprechen, wenn die Schlussfolgerung darin besteht, dass Sie sie in einer beliebigen Methode verwenden können oder nicht, gibt es keinen Grund, warum Sie zu einer anderen Schlussfolgerung kommen sollten, wenn es sich um die Methode main handelt.

Offenbar soll "sollten wir ..." eigentlich fragen, ob "sollten wir vermeiden ...". Wenn das die Frage ist, dass es keine speziellen Regeln für die Methode main gibt, wenn es einen Grund gibt, die Verwendung der Stream-API zu verbieten, gilt dieser Grund auch für alle anderen Methoden, was die Stream-API zu einer unbrauchbaren API macht . Die Antwort ist natürlich, dass es keinen Grund gibt, die Stream-API in der main-Methode zu verbieten.


Bezüglich Speicherverbrauch, beim Ersetzen einer für-jede Schleife mit einer Collection.forEach Methodenaufruf, man eine Iterator weise für eine Lambda-Instanz handeln, so in der Anzahl und Größe der erzeugten Objektinstanzen keinen signifkanten Unterschied haben . Wenn Sie Stream forEach verwenden, fügen Sie eine Spliterator und eine Stream Instanz hinzu, die immer noch als unbedeutend betrachtet werden kann, auch wenn Ihre Anwendung nur aus der main-Methode besteht. Der von einer JVM vorab zugewiesene Speicher ist viel größer als der von diesen wenigen Objekten belegte Speicher, und Ihre Objekte passen sehr wahrscheinlich in den lokalen Zuordnungsspeicher der Threads. Mit anderen Worten, von außerhalb der JVM gibt es keinen Unterschied in dem Speicher, der von dem Prozess verwendet wird.

Wie Sie erwähnt der Begriff „Puffer“, die konzeptuelle, was Sie sollte wissen ist, dass ein Strom macht nicht Pufferelemente für die meisten Operationen (einschließlich forEach), so, und zwar unabhängig davon, ob Sie eine Sammlung über die Schleife durchqueren oder Stream, in beiden Fällen wird niemals eine Speicherskalierung mit der Größe der Collection zugewiesen, sodass der Unterschied, falls vorhanden, so klein bleibt, wie oben beschrieben, unabhängig davon, ob Sie über drei Elemente wie in Ihrem Beispiel oder über drei Millionen Elemente iterieren.


Auf Problem, das Verwirrung stiften könnte, ist, dass Sie nicht Multi-Threaded-Operationen in einer Klasseninitialisierer verwenden sollten, die, dass Sie sollten nicht einen parallel Strom in einem Klasseninitialisierer verwenden impliziert. Aber das verbietet Stream-Operationen an sich nicht, ferner ist die main-Methode kein Klasseninitialisierer; Wenn die Methode main aufgerufen wird, wurde die Klasse bereits initialisiert.

+0

* "Wenn Sie eine For-Each-Schleife durch einen Collection.forEach-Methodenaufruf ersetzen, handeln Sie eine Iterator-Instanz für eine Lambda-Instanz" * ... Sie meinen ein "Iterable.forEach"? Oder es gibt etwas, das ich missverstanden habe ... trotzdem +1. –

+1

@ Jean-François Savard: Ja, 'forEach' ist in' Iterable' definiert, aber diese 'Default'-Implementierung verwendet einen 'Iterator', während die meisten Collections, vor allem' ArrayList', die Möglichkeit nutzen, ein optimiertes 'forEach' bereitzustellen Implementierung, die iteriert, ohne eine 'Iterator'-Instanz zu erstellen. Das ist das zu berücksichtigende Szenario, z.B. im Code der Frage. Während ich an dieses Szenario dachte, vergaß ich einfach, dass "forEach" nicht nur eine Collection-Methode ist, sondern auch in der abstrakteren "Iterable" -Schnittstelle definiert ist. – Holger

2

Bei Interviewfragen nicht davon ausgehen, dass jede Ja/Nein-Frage auf diese beiden Möglichkeiten beschränkt ist. Eine gute Antwort könnte sein: "Es gibt keinen Unterschied".

In diesem Fall haben sie möglicherweise nach Ihnen gesucht, um zu erkennen, dass list.foreach() effizienter ist als list.stream().foreach().

+0

hallo hank. ..Looping war nur ein Beispiel ... im echten Fall meine ich im Interview, dass ich etwas anderes wie dieses list.stream() geschrieben habe. filter (etwas, das boolean zurückliefert). Also das einzige war ..... ist es richtig, stream in main() zu schreiben? –