2016-07-11 37 views
7

Volevo scrivere una funzione pura con Java 8 che prendesse una raccolta come argomento, applicasse alcune modifiche a ogni oggetto di quella raccolta e restituisse una nuova raccolta dopo l'aggiornamento. Voglio seguire i principi FP quindi non voglio aggiornare/modificare la collezione che è stata passata come argomento.Java 8 modifica elementi stream

Esiste un modo per farlo con Stream API senza prima creare una copia della raccolta originale (e quindi utilizzando forEach o "normale" per loop)?

oggetto del campione qui sotto e lascia supporre che voglio per aggiungere un testo a una delle proprietà dell'oggetto:

public class SampleDTO { 
    private String text; 
} 

Quindi voglio fare qualcosa di simile al di sotto, ma senza modificare la raccolta. Supponendo che "elenco" è un List<SampleDTO>.

list.forEach(s -> { 
    s.setText(s.getText()+"xxx"); 
}); 
+1

Direi che questo va un po 'contro il principio della programmazione funzionale qui. L'idea è di non mutare lo stato, ma creare un nuovo stato come prodotto della funzione. Ecco perché, invece di modificare l'elenco originale, dovresti utilizzare la funzione 'map' fornita dall'API Java stream per creare un nuovo elenco. – christopher

risposta

12

è necessario disporre di un metodo/costruttore che genera una copia di un SampleDTO un'istanza esistente, come ad esempio un costruttore di copia.

Poi si può map ciascun originale SampleDTO esempio per una nuova SampleDTO esempio, e li collect in un nuovo List:

List<SampleDTO> output = 
    list.stream() 
     .map(s-> { 
        SampleDTO n = new SampleDTO(s); // create new instance 
        n.setText(n.getText()+"xxx"); // mutate its state 
        return n; // return mutated instance 
       }) 
     .collect(Collectors.toList()); 
2

Per rendere in questo modo più elegante vorrei suggerire a creare un Method con nella classe.

public class SampleDTO { 
private String text; 
public String getText() { 
    return text; 
} 

public void setText(String text) { 
    this.text = text; 
} 

public SampleDTO(String text) { 
    this.text = text; 
} 

public SampleDTO getSampleDTO() { 
    this.setText(getText()+"xxx"); 
    return this; 
} 
    } 

e inserirlo come:

List<SampleDTO> output =list.stream().map(SampleDTO::getSampleDTO).collect(Collectors.toList(); 
+0

@FedericoPeraltaSchaffner Grazie per il commento e downvot. Ho risolto questo. ora compilerò – soorapadman

+0

I downvoted perché la tua risposta ha avuto 1 voto e volevo promuovere altre risposte che erano corrette, scusa se era troppo dura.Ora che lo hai corretto, non solo ho ripristinato il mio downvote, ma ho anche upvoted. –

+0

Tuttavia, ora l'oggetto originale è stato modificato e OP non voleva mutare né l'elenco originale né i suoi elementi. Dovresti considerare di creare una copia dell'oggetto originale con il suo attributo di testo modificato. –

1

Streams sono immutabili come corde di così non si può andare in giro la necessità di creare un flusso di nuova/list/array

Detto questo è possibile utilizzare. Collect() per restituire una nuova collezione cambia post in modo

List<Integer> result = inList.stream().map().Collect() 
1

Penso che sarebbe meglio, soprattutto se si esegue il lavoro multi-thread, per lo streaming della lista originale in una nuova lista modificata o qualsiasi altra cosa è desiderata.

La nuova lista o mappa o qualsiasi altra struttura desiderata può essere creata come parte del processo di streaming.

Quando il processo di streaming è completato, è sufficiente scambiare l'originale con il nuovo.

Tutto ciò deve verificarsi in un blocco sincronizzato.

In questo modo si ottengono le massime prestazioni e il parallelismo per la riduzione o qualsiasi cosa si stia facendo e si finisce con uno scambio atomico.

Problemi correlati