Java 8 nested streams: return value on last stream
This question can be thought of as based on java 8 nested streams
Suppose I have Batch
with Basket
with Item
:
public class Batch {
private List<Basket> baskets;
}
public class Basket {
private List<Item> items;
}
public class Item {
private String property;
private int value;
}
I would like to rewrite this method with Java 8 streams.
public class SomeService {
public int findValueInBatch(Batch batch) {
for (Basket basket : batch.getBaskets()) {
for (Item item : basket.getItems()) {
if (item.getProperty().equals("someValue") {
return item.getValue();
}
}
}
return 0;
}
}
How should I do it?
First step to where I want to go:
public int findValueInBatch(Batch batch) {
for (Basket basket : batch.getBaskets()) {
basket.getItems().stream()
.filter(item -> item.getProperty.equals("someValue")
.findFirst()
.get();
// there I should 'break'
}
}
Many thanks.
source to share
baskets.stream()
.flatMap(basket -> basket.getItems().stream())
.filter(item -> item.equals("someValue"))
.findAny()
.orElseThrow(NoSuchElementException::new);
The advantage of using findAny
instead findFirst
is that it findFirst
doesn't work with parallel threads. Therefore, if you want to parallelize the above operation, you will need to replace the method stream()
withparallel()
source to share
- Use
flatMap
to get a list of nested lists, extract each oneList<Item>
and concatenate them intoStream<Item>
, it acts as if all sub-streams were concatenated together. - Use
filter
to ignore irrelevant items. - Use
findFirst
to get only the first case and stop processing - Use
orElseThrow
to throw an exception if someValue was not found .
Here you are,
public class SomeService {
public int findValueInBatch(Batch batch) {
return batch.getBaskets().stream()
.flatMap(basket -> basket.getItems().stream())
.filter(item -> item.getProperty.equals("someValue"))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("value not found"));
}
}
source to share
To eliminate both loops, you can use flatMap
to create Stream<Item>
all Item
all Basket
:
return batch.getBaskets()
.stream()
.flatMap(b -> b.getItems().stream())
.filter(item -> item.getProperty.equals("someValue"))
.findFirst()
.orElse(some default value); // using .get() would throw an exception
// if no match is found
source to share