I have a stream of generic items. I'd like to print the class name of the first item + the toString()
of all the items.
If I had an Iterable, it would look like this:
Iterable<E> itemIter = ...; boolean first = true; for (E e : itemIter) { if (first) { first = false; System.out.println(e.getClass().getSimpleName()); } System.out.println(e); }
Can I do this on a stream (Stream<T>
) with the stream API?
* Please note that it's a question about streams - not about iterators. I have a stream - not an iterator.
Stream skip(n) method is used to skip the first 'n' elements from the given Stream. The skip() method returns a new Stream consisting of the remaining elements of the original Stream, after the specified n elements have been discarded in the encounter order.
The get() method of the ArrayList class accepts an integer representing the index value and, returns the element of the current ArrayList object at the specified index. Therefore, if you pass 0 to this method you can get the first element of the current ArrayList and, if you pass list.
Using Stream.collect() The second method for calculating the sum of a list of integers is by using the collect() terminal operation: List<Integer> integers = Arrays. asList(1, 2, 3, 4, 5); Integer sum = integers. stream() .
There is StreamEx
library that extends standard Java's Stream API. Using StreamEx.of(Iterator)
and peekFirst
:
StreamEx.of(itemIter.iterator()) .peekFirst(e -> System.out.println(e.getClass().getSimpleName())) .forEach(System.out::println);
If your starting point is a Stream
and you want to retain all of its properties and the laziness, the following solution will do:
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); }
E.g. when you use it with
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(" | ")));
it will print
blah (String) BLAH | BAR | BAZ
demonstrating that the processing will not start before commencing the terminal operation (collect
), hence reflecting the preceding update to the source List
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With