2014-04-24 8 views
5

Ci sono dei vantaggi nell'utilizzo della nuova API Stream per semplici iterazioni?Devo usare Stream API per una semplice iterazione?

Senza API Stream:

for (Map.Entry<String, String> entry : map.entrySet()) { 
     doSomething(entry); 
    } 

Utilizzando API Stream:

map.entrySet().stream().forEach((entry) -> { 
     doSomething(entry); 
    }); 

lunghezza e la leggibilità del codice sono circa lo stesso. Ci sono delle differenze importanti (ad es. Nelle prestazioni)?

+2

Flussi dovrebbe essere usato se può rendere il codice più breve * e * più leggibile . Quindi il tuo caso d'uso non è un buon esempio da solo. Tuttavia, se si utilizza il metodo 'map.forEach' stesso, allora vi è un certo punto nell'utilizzo di lambdas, ma poi di nuovo, non si stanno più utilizzando flussi in quel punto. – skiwi

+3

Lo stesso vale per entrySet; puoi dire 'map.entrySet(). forEach (...)' senza la necessità di un flusso. Nel caso di una singola chiamata di metodo, la forma 'map.entrySet(). ForEach (context :: doSomething);' è preferibile a un'espressione lambda in quanto è * veramente * più breve e più leggibile. Quindi, se hai un * metodo * esistente 'doSomething 'che prende una singola istanza di voce o due parametri che corrispondono a chiave e valore, allora c'è un punto nell'usare' forEach (...) '. – Holger

+2

Inoltre, anche se lo si scrive in questo modo, non sono necessarie le parentesi nel secondo esempio. Penso che sia più leggibile in questo modo ... – Veluria

risposta

5

L'API Streams rende il parallelismo molto più facile da realizzare (anche se vedrete solo i vantaggi con una raccolta di grandi dimensioni). Se è stato necessario implementare il parallelismo sul tuo primo esempio allora ci sarebbe una differenza notevole nella quantità di codice (in contrapposizione ad aggiungere .parallelStream() per il secondo esempio)

Come per il Java Trail on parallelism:

Una difficoltà nell'implementare il parallelismo in applicazioni che utilizzano le raccolte è che le raccolte non sono thread-safe, il che significa che i thread multipli non possono manipolare una raccolta senza introdurre interferenze di thread o errori di coerenza della memoria. Le Collezioni Framework fornisce wrapper di sincronizzazione, che aggiungono la sincronizzazione automatica a una raccolta arbitraria, rendendola thread-safe. Tuttavia, la sincronizzazione introduce la contesa del thread. Si desidera che eviti il ​​conflitto di thread perché impedisce l'esecuzione di thread nel parallelo . Le operazioni aggregate e i flussi paralleli consentono di implementare il parallelismo con le raccolte senza sicurezza di thread, a condizione che non modifichi la raccolta mentre si sta operando su di essa. Nota: che parallelismo non è automaticamente più veloce di eseguire operazioni in serie, anche se può essere se si dispone di sufficienti dati e core di processore . Mentre le operazioni di aggregazione consentono di semplificare il parallelismo con lo strumento , è comunque responsabilità dell'utente determinare se l'applicazione è adatta per il parallelismo .

3

Lei aveva chiesto di Streams, ma come commento di skiwi notato, passando un lambda al metodo forEach di default sulla mappa possibilmente riempie il conto se l'iterazione è semplice e non richiede il parallelismo o qualsiasi logica aggiuntiva. Supponendo che doSomething può essere riscritta per prendere chiave e valori args separati invece di un Map.Entry, questo può essere ridotto ad una battuta:

map.forEach(MyClass::doSomething); // if doSomething is a static method 

    map.forEach(this::doSomething);  // if doSomething is an instance method