2015-09-19 10 views
11

Scrivendo applicazioni in Java esistono molti casi d'uso per java.util.Collection. Poiché java.util.stream.Stream è stato introdotto con Java 8, ho trovato alcuni casi d'uso in cui è difficile decidere cosa utilizzare.Decisione tra l'uso di uno stream o di un loop

Ad esempio: Scriverete alcuni metodi di utilizzo.

public static List<?> filterHashToList(int hash, Collection<?> toFilter) { 
    return toFilter.stream() 
     .filter((Object o) -> hash == o.hashCode()) 
     .collect(Collectors.toCollection(LinkedList::new)); 
} 

Che a scrivere in questo modo:

public static List<?> filterHashToList(int hash, Collection<?> toFilter) { 
    List<Object> result = new LinkedList<>(); 

    for(Object o : toFilter) { 
     if(hash == o.hashCode()) { 
      result.add(o); 
     } 
    } 

    return result; 
} 

Entrambi i metodi produrrebbe lo stesso risultato. java.util.stream.Stream e java.util.stream.Collector sono interfacce, quindi l'implementazione può variare anche se utilizzo flussi e collettori personalizzati.

Penso che ci siano un sacco di implementazioni là fuori usando il loop-way old-fashoined.

Quindi, è possibile rispondere a cosa utilizzare, streaming o loop, da use-case? E se sì, tutte le implementazioni devono essere aggiornate dove appropriato?

O dovrei anche fornire entrambi i modi implementando metodi di utilizzo? O dovrei anche fornire un mthed per restituire il flusso dopo il processo di filtraggio in modo da poter lavorare anche con quello, se necessario?

+0

È possibile avere un parallelismo molto semplice con gli Stream, sono più compatti (alcuni potrebbero essere più "leggibili") e hanno ulteriori vantaggi, se i flussi sono veri "flussi" (qualcosa scorre, dinamicamente - non basato su un raccolta fissa come qui). Ma nel tuo caso particolare, penso che potresti andare in entrambi i modi. – mastov

+0

Quindi possiamo accorciare a: Gli stream devono essere preferibili, ma in casi di facile utilizzo entrambi vanno bene? – narranoid

+3

Vorrei usare due semplici regole: 1. se non è rotto, non aggiustarlo. 2. usa quello che trovi più leggibile e manutenibile. Detto questo, i tuoi due esempi non restituiscono la stessa cosa: uno restituisce un oggetto ArrayList e l'altro restituisce un oggetto LinkedList. –

risposta

5

noti che nell'implementazione si bastone con specifica conseguente raccolta di tipo LinkedList che di solito ha prestazioni molto scarsa rispetto ad ArrayList. Cosa succede se l'utente del metodo desidera utilizzare l'elenco risultante in modalità accesso casuale? Probabilmente l'utente di questo metodo ha bisogno di un array, perché dovrebbe essere passato ad un altro metodo API che accetta un array. A volte l'utente deve solo sapere quanti oggetti con hashCode sono presenti nella collezione di input, quindi non c'è bisogno di creare un elenco risultante. Il modo in cui Java-8 è quello di tornare flussi dai metodi, non le collezioni e lasciare che il chiamante decidere come raccoglierla:

public static <T> Stream<T> filterHashToList(int hash, Collection<T> toFilter) { 
    return toFilter.stream() 
     .filter(o -> hash == o.hashCode()); 
} 

e usarlo:

filterHashToList(42, input).count(); 

O

filterHashToList(42, input).collect(toCollection(ArrayList::new)); 

O

filterHashToList(42, input).toArray(); 

Questa wa y il metodo diventa molto semplice, quindi probabilmente non ne hai affatto bisogno, ma se vuoi fare un filtro/trasformazione più sofisticato, va bene.

Quindi, se non si desidera modificare l'API e restituire ancora il LinkedList, non è necessario modificare l'implementazione. Ma se vuoi approfittare dell'utilizzo di Stream API, è meglio cambiare il tipo di ritorno in Stream.

8

In assenza di una risposta postata citerò Brian Goetz che riecheggia il mio sentimento e sospetto molti altri ".

Non c'è nulla di magico in entrambi i flussi o loop. Dovresti scrivere il codice che è più leggibile, chiaro e manutenibile. Ciascuno di questi è accettabile.

0

Penso che questo dipenda in larga misura dalle dimensioni previste della Collezione e dall'applicazione pratica del programma. Il primo è leggermente più efficiente, ma lo trovo meno leggibile e ci sono ancora sistemi che girano su Java 7 (cioè Google App Engine). Inoltre, quest'ultimo sarebbe probabilmente più facile aggiungere filtri più complessi per andare avanti. Tuttavia, se l'efficienza è la preoccupazione principale, vorrei andare con il primo.

Problemi correlati