mi chiedo c'è un'alternativa alGet ultimi n elementi dal flusso
List<X> lastN = all.subList(Math.max(0, all.size() - n), all.size());
con stream utilizzo?
mi chiedo c'è un'alternativa alGet ultimi n elementi dal flusso
List<X> lastN = all.subList(Math.max(0, all.size() - n), all.size());
con stream utilizzo?
È possibile scrivere un collettore personalizzato come questo:
public static <T> Collector<T, ?, List<T>> lastN(int n) {
return Collector.<T, Deque<T>, List<T>>of(ArrayDeque::new, (acc, t) -> {
if(acc.size() == n)
acc.pollFirst();
acc.add(t);
}, (acc1, acc2) -> {
while(acc2.size() < n && !acc1.isEmpty()) {
acc2.addFirst(acc1.pollLast());
}
return acc2;
}, ArrayList<T>::new);
}
e usarlo in questo modo:
List<String> lastTen = input.stream().collect(lastN(10));
Non è necessario scrivere 'ArrayList
@Holger, prima ho scritto 'ArrayList :: new', ma Eclipse ha mostrato un avvertimento sul costruttore non controllato. Bene, probabilmente questo è un problema specifico della CGE. –
È interessante notare che 'ArrayDeque :: new' trarrebbe vantaggio da un testimone di tipo, poiché l'uso di' ArrayDeque
Uso Stream.skip()
restituisce un flusso costituito dai restanti elementi di questo flusso dopo scartando i primi n elementi del flusso. Se questo flusso contiene meno di n elementi, verrà restituito uno stream vuoto.
all.stream().skip(Math.max(0, all.size() - n)).forEach(doSomething);
Nel caso in cui il torrente ha una dimensione sconosciuta, probabilmente non c'è modo per aggirare consumando l'intero flusso e il buffering ultimi n
elementi incontrati finora. Puoi farlo usando un qualche tipo di deque, o un buffer ad anello specializzato che mantiene automaticamente la sua dimensione massima (vedi this related question per alcune implementazioni).
public static <T> List<T> lastN(Stream<T> stream, int n) {
Deque<T> result = new ArrayDeque<>(n);
stream.forEachOrdered(x -> {
if (result.size() == n) {
result.pop();
}
result.add(x);
});
return new ArrayList<>(result);
}
Tutte queste operazioni (size
, pop
, add
) dovrebbe avere complessità O (1), quindi complessità generale per un flusso con (sconosciuta) lunghezza n sarebbe O (n).
Non credo che questo è generalmente possibile con i flussi, come le dimensioni di un corso d'acqua non possono essere noto a priori, o potrebbe anche essere infinito. E se si crea lo stream da una lista, basta usare la sottolista, come hai fatto tu. –
@tobias_k l'OP sembra avere comunque una lista finita ... – Puce
Se hai già una lista, allora 'subList' è la strada da percorrere. Puoi quindi copiarlo, riprodurlo in streaming e qualsiasi altra cosa desideri. –