Ich habe eine Klasse, die einen Stream<X>
von Elementen liefern können soll:
interface Data { Stream<X> getStream(); }
Dabei ist nicht festgelegt, wo dieser Stream herkommt. Er kann von einer List<X>
stammen, die direkt in dieser Klasse liegt:
class DataWithList implements Data {
List<X> list;
Stream<X> getStream() { return list.stream(); }
}
In einem anderen Fall ist die Quelle aber über einen Supplier wegabstrahiert. Ganz grob also sowas:
class DataWithSupplier implements Data {
Supplier<Stream<X>> supplier;
Stream<X> getStream() { return supplier.get(); }
}
Wobei der „Supplier“ natürlich auch eine List
sein könnte. Aber das weiß man nicht. Er könnte auch „kompliziert“ sein, und den Stream aufwändig zusammenbauen müssen.
Deswegen habe ich in einem umnachteten Moment gedacht: Joa, ich bau’ da mal so eine Art Cache ein:
class DataWithCachedSupplier implements Data {
Supplier<Stream<X>> supplier;
List<X> cached;
Stream<X> getStream() {
if (cached != null) return cached.stream();
cached = new ArrayList<X>();
return supplier.get().map(x -> {
cached.add(x);
return x;
});
}
}
Zugegeben ich muss schon SEHR umnachtet gewesen sein: Das macht natürlich gar keinen Sinn. Wenn jemand
data.getStream().limit(5).forEach(...);
data.getStream().forEach(...);
macht, kommen beim zweiten mal nur die 5 gecachten Elemente an…
Man könnte nun natürlich direkt sagen: Was auch immer das für ein Supplier
ist, ich pack’ erstmal alles, was dem seine Streams liefern, in eine List
, und die Sache hat sich erledigt. Aber ich hatte gehofft, dass man das caching irgendwie geschickt „on the fly“ machen könnte.
Hat jemand eine Idee?