user44986
user44986

Reputation: 163

Find element in a list and change it using stream()

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

Answers (1)

user140547
user140547

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

Related Questions