Perché dovrei usare "operazioni funzionali" invece di un ciclo for?

38
for (Canvas canvas : list) {
}

NetBeans mi suggerisce di utilizzare "operazioni funzionali":

list.stream().forEach((canvas) -> {
});

Ma perché questo preferito ? Se mai, è più difficile da leggere e capire. Stai chiamando stream() , quindi forEach() utilizzando un'espressione lambda con parametro canvas . Non vedo come sia più carino del loop for nel primo frammento.

Ovviamente sto parlando solo di estetica. Forse c'è un vantaggio tecnico qui che mi manca. Che cos'è? Perché dovrei usare il secondo metodo invece?

    
posta Omega 13.09.2015 - 21:12
fonte

3 risposte

45

Gli stream forniscono un'astrazione molto migliore per la composizione delle diverse operazioni che vuoi eseguire in aggiunta alle raccolte o agli stream di dati in arrivo. Specialmente quando devi mappare gli elementi, filtrarli e convertirli.

Il tuo esempio non è molto pratico. Considera il seguente codice dal sito Oracle .

List<Transaction> groceryTransactions = new Arraylist<>();
for(Transaction t: transactions){
  if(t.getType() == Transaction.GROCERY){
    groceryTransactions.add(t);
  }
}
Collections.sort(groceryTransactions, new Comparator(){
  public int compare(Transaction t1, Transaction t2){
    return t2.getValue().compareTo(t1.getValue());
  }
});
List<Integer> transactionIds = new ArrayList<>();
for(Transaction t: groceryTransactions){
  transactionsIds.add(t.getId());
}

può essere scritto usando i flussi:

List<Integer> transactionsIds = 
    transactions.stream()
                .filter(t -> t.getType() == Transaction.GROCERY)
                .sorted(comparing(Transaction::getValue).reversed())
                .map(Transaction::getId)
                .collect(toList());

La seconda opzione è molto più leggibile. Quindi, quando hai cicli nidificati o loop diversi che eseguono l'elaborazione parziale, è un'ottima candidata per l'utilizzo delle API Streams / Lambda.

    
risposta data 13.09.2015 - 21:24
fonte
16

Un altro vantaggio dell'utilizzo dell'API di streaming funzionale è che nasconde i dettagli di implementazione. Descrive solo cosa dovrebbe essere fatto, non come. Questo vantaggio diventa ovvio quando si guarda al cambiamento che deve essere fatto, per passare dall'esecuzione di un singolo thread a un codice parallelo. Cambia semplicemente .stream() in .parallelStream() .

    
risposta data 14.09.2015 - 00:11
fonte
13

If anything, it is harder to read and understand.

Questo è altamente soggettivo. Trovo la seconda versione molto più facile da leggere e capire. Corrisponde al modo in cui altri linguaggi (es. Ruby, Smalltalk, Clojure, Io, Ioke, Seph) lo fanno, richiede meno concetti da capire (è solo una normale chiamata di metodo come qualsiasi altra, mentre il primo esempio è la sintassi specializzata).

Se non altro, è una questione di familiarità.

    
risposta data 14.09.2015 - 05:17
fonte

Leggi altre domande sui tag