Perché dovresti avere bisogno di una riflessione per ottenere la pigrizia? Ad esempio, si consideri questa classe:
class LazySeq<T> {
private final List<T> list;
private Predicate<? super T> predicate;
public LazySeq(List<T> input) {
this.list = new ArrayList<>(input);
}
//Here you just store the predicate, but you don't perform a filtering
//You could also return a new LazySeq with a new state
public LazySeq<T> filter(Predicate<? super T> predicate) {
this.predicate = predicate;
return this;
}
public void forEach(Consumer<? super T> consumer){
if(predicate == null) {
list.forEach(consumer);
} else {
for(T elem : list) {
if(predicate.test(elem)) {
consumer.accept(elem);
}
}
}
}
}
Quando si chiama filter
sulla ss pigro, il filtraggio non avviene immediatamente in modo, ad esempio:
LazySeq<Integer> lazySeq = new LazySeq<>(Arrays.asList(1, 2, 3, 4));
lazySeq = lazySeq.filter(i -> i%2 == 0);
Se si vede il contenuto della sequenza dopo la chiamata filtro, vedrai che è sempre 1, 2, 3, 4
. Tuttavia, quando si chiama un'operazione terminale, ad esempio forEach
, il filtro verrà eseguito prima di utilizzare il consumatore. Così, per esempio:
lazySeq.filter(i -> i%2 == 0).forEach(System.out::println);
stamperà 2 e 4.
Questo è lo stesso principio con Stream
s. Da una sorgente, si concatenano operazioni che hanno proprietà determinate. Queste operazioni sono intermedie, che restituisce un flusso lento (ad esempio filter
o map
) o un terminale (ad esempio forEach
). Alcune di queste operazioni di terminale sono in cortocircuito (come ad esempio findFirst
), quindi non si può attraversare tutta la pipeline (si può pensare ad un ritorno anticipato in un ciclo for che restituisce l'indice di un valore in una matrice per esempio).
Quando si chiama un'operazione terminale, questa catena di operazioni inizia ad essere eseguita in modo che alla fine si ottenga il risultato previsto.
La pigrizia può essere ottenuta memorizzando un nuovo stato sulla pipeline quando viene applicato un op intermedio e quando si chiama un terminale op, si passano tutti gli stati uno ad uno sui dati.
L'API Stream non è realmente implementata in questo modo (è un po 'più complessa) ma in realtà il principio è qui.
Ho accettato la risposta di Alexi perché mi dava un'idea migliore di ciò che stavo cercando. Ma la risposta di HuStmpHrrr sembra più raffinata. Ringrazia tutti. – Learner