Reputation: 163
Is it possible to find an element in a List
, change it or throw Exception
if the element wasn't found, using Java 8 stream?
In other words, I would like to rewrite following code using stream
. The best I could get is to change the item value, but no way to find out if an item was found/changed.
boolean isFound = false;
for (MyItem item : myList) {
if (item.getValue() > 10) {
item.setAnotherValue(5);
isFound = true;
}
}
if (!isFound) {
throw new ElementNotFoundException("Element 10 wasn't found");
}
Upvotes: 4
Views: 6683
Reputation: 8200
If your goal is to only find a single element, you could do
MyItem item = l.stream()
.filter(x -> x.getValue() > 10)
.findAny() // here we get an Optional
.orElseThrow(() -> new RuntimeException("Element 10 wasn't found"));
item.setAnotherValue(4);
In Java 9, using ifPresentOrElse
, this can be somewhat simplified to (unfortunately the syntax ()->{throw new RuntimeException();}
is also a bit clumsy, but AFAIK it can't be simplified):
l.stream()
.filter(x -> x.getValue() > 10)
.findAny() // here we get an Optional
.ifPresentOrElse(x->x.setAnotherValue(5),
()->{throw new RuntimeException();});
If you want to do that for all items, you can try something like that. But as Java 8 Streams are not designed to operate via side effects, this it not a really clean approach:
AtomicBoolean b = new AtomicBoolean(false);
l.stream()
.filter(x -> x.getValue() > 10)
.forEach(x->{
x.setAnotherValue(5);
b.set(true);
});
if (b.get()){
throw new RuntimeException();
}
Of course, you could also just simply collect the elements into a list and then do your operations. But I am not sure if this is any improvement over the simple for-loop you started with...
Well if forEach
returned a long
which represents the number of elements it was invoked on, this would be easier...
Upvotes: 11