Pradyot
Pradyot

Reputation: 3059

Storing/Reusing intermediate results on a java 8 stream

I have a List of A , To execute filtering I need to map A to B. But once the filtering logic is done I still need A for further operations, So My question is would it be at all possible to achieve this? One approach I can think of is storing both A and B into a third type, so I have both available, while processing the stream, but not sure that is elegant and wondering if here is a better way.Or am I trying to fit a square peg in a round hole by using streams.

List<A> a;
List<B> b = a.stream().map(i -> load(i)).filter(need A here in addition to b)

Upvotes: 8

Views: 1284

Answers (3)

Jean-Baptiste Yun&#232;s
Jean-Baptiste Yun&#232;s

Reputation: 36431

You can use an anonymous class on the fly (or any appropriate existing class to represent a pair or alike) as:

a.stream().map(e -> new Object() { A a=e; B b=load(e); })
          .filter(x -> /*any code using x.a and x.b */)

Be aware that some IDEs doesn't accept this while it is perfect valid Java 8 code.

Upvotes: 0

Andrew
Andrew

Reputation: 49646

There is no elegant solution here, but you could do filtering within mapping:

.map(a -> {
    B b = load(a);
    return filter(a, b) ? b : null;
})
.filter(Objects::nonNull)

You don't need to create wrappers around the stream elements. The load method will be executed only once in case it is an expensive operation.

null is the default invalid value, it should be replaced if null is allowed or it can be returned from load.

Upvotes: 1

Eugene
Eugene

Reputation: 120968

Well you can always pass two things wrapped into a Pair, array, List for example:

a.stream().map(i -> List.of(load(i), i)) // List#of is java-9, replace with Pair or array
          .filter(x -> x[0]...)
          .filter(y -> /* y is List here */)

Upvotes: 3

Related Questions