Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get the first element while continue streaming?

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.

like image 741
AlikElzin-kilaka Avatar asked Mar 06 '19 16:03

AlikElzin-kilaka


People also ask

How do I skip the first element in a stream?

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.

How do I find the first element of a list?

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.

How do I add all elements to a stream 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() .


2 Answers

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); 
like image 66
Ruslan Avatar answered Oct 02 '22 13:10

Ruslan


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.

like image 31
Holger Avatar answered Oct 02 '22 13:10

Holger