Java >> Java tutorial >  >> Tag >> while

Hvordan får jeg det første element, mens jeg fortsætter med at streame?

Der er StreamEx bibliotek, der udvider standard Javas Stream API. Bruger StreamEx.of(Iterator) og peekFirst :

StreamEx.of(itemIter.iterator())
        .peekFirst(e -> System.out.println(e.getClass().getSimpleName()))
        .forEach(System.out::println);

Hvis dit udgangspunkt er en Stream og du ønsker at bevare alle dens egenskaber og dovenskaben, vil følgende løsning gøre:

public static <E> Stream<E> forFirst(Stream<E> stream, Consumer<? super E> c) {
    boolean parallel = stream.isParallel();
    Spliterator<E> sp = stream.spliterator();
    return StreamSupport.stream(() -> {
        if(sp.getExactSizeIfKnown() == 0) return sp;
        Stream.Builder<E> b = Stream.builder();
        if(!sp.tryAdvance(b.andThen(c))) return sp;
        return Stream.concat(b.build(), StreamSupport.stream(sp, parallel)).spliterator();
    }, sp.characteristics(), parallel);
}

For eksempel. når du bruger det med

List<String> list = new ArrayList<>(List.of("foo", "bar", "baz"));
Stream<String> stream = forFirst(
        list.stream().filter(s -> s.startsWith("b")),
        s -> System.out.println(s+" ("+s.getClass().getSimpleName()+')')
    ).map(String::toUpperCase);
list.add(1, "blah");
System.out.println(stream.collect(Collectors.joining(" | ")));

den udskrives

blah (String)
BLAH | BAR | BAZ

demonstrerer, at behandlingen ikke starter, før terminaloperationen påbegyndes (collect ), hvilket afspejler den foregående opdatering til kilden List .


Native løsning: Stream i Java kan ikke genbruges. Dette betyder, at forbrugende stream kun kan udføres én gang. Hvis du får det første element fra en strøm, kan du gentage det en gang til.

Løsning ville være at oprette en anden strøm, der er den samme som den første, eller at hente det første element og derefter oprette en strøm, sådan noget:

Stream<E> stream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(sourceIterator, Spliterator.ORDERED), false);
E firstElement = itemIter.next();
stream.foreach(...);

Rediger

Der er ikke rigtig nogen måde at "kopiere" en stream, du skal beholde en iterator/samling. Mere om det her. Når det kommer til hukommelsen, når streamen er opbrugt, kan den opsamles af skraldemand, da den ikke nytter noget. Stream i sig selv tager ikke mere plads end iterator den stammer fra. Husk, at strømme potentielt kan være uendelige. Elementer, der aktuelt manipuleres, gemmes i hukommelsen.


Java tag