Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Map first element of stream differently than rest

Is there a way in Java's Stream API to map first element of stream differently than other?

Equivalent of this code:

List<Bar> barList = new ArrayList<>();

for (int i=0; i<fooList.size(); i++) {
    Foo foo = fooList.get(i);
    Foo modifiedFoo = foo.getModifiedFoo();
    if (i == 0) {
        barList.add(new Bar(modifiedFoo, false));
    }else {
        barList.add(new Bar(modifiedFoo, true));
    }
}

Stream<Bar> = barList.stream();

Note: I already have a stream setup and I would want some operation after first mapping

fooList.stream()
        .map(Foo::getModifiedFoo)
        .(May be Some operation here to get different new Bar for first modifiedFoo)
        .map(modifiedFoo -> new Bar(modifiedFoo, true));
like image 957
ankitkpd Avatar asked Mar 23 '18 18:03

ankitkpd


People also ask

How do I find the first element of a stream?

To get the first element, you can directly use the findFirst() method. This will return the first element of the stream.

Does stream map keep order?

A parallel stream is performed one or more elements at a time. Thus the map() would preserve the encounter of the stream order but not the original List's order.

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.

Do streams change the original data structure?

Streams don't change the original data structure, they only provide the result as per the pipelined methods. Each intermediate operation is lazily executed and returns another stream as a result, hence various intermediate operations can be pipelined.


1 Answers

I would get the first element, create a Stream out of it and apply the needed mappings. Then, I'd take the rest of the list, create a stream out of it and apply the different mappings. Then concat the streams. Something like this:

Stream<Bar> first = Stream.of(fooList.get(0))
    .map(Foo::getModifiedFoo)
    .map(modifiedFoo -> new Bar(modifiedFoo, false));

Stream<Bar> others = fooList.subList(1, fooList.size()).stream()
    .map(Foo::getModifiedFoo)
    .map(modifiedFoo -> new Bar(modifiedFoo, true));

Stream<Bar> bars = Stream.concat(first, others).flatMap(s -> s);

Another approach:

Stream<Bar> bars = IntStream.range(0, fooList.size())
    .mapToObj(i -> new Bar(fooList.get(i).getModifiedFoo(), i > 0));

This way is succinct and does the job pretty well.

like image 161
fps Avatar answered Sep 21 '22 13:09

fps