Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java streams: throwing exception from stream depending upon value in stream

Consider below dummy code:

List<Integer> intList = new ArrayList<>();
intList.add(10);
intList.add(20);
intList.add(30);

intList.stream().filter(i -> i > 40)
    .throwIf(size of list <= 0)
    .collect(Collectors.toList());

is there any feature available in java streams which will achieve something like above code?

Note: Above code is just the representation of what I am doing, its not the exact code I am looking for.

like image 310
eatSleepCode Avatar asked Mar 03 '16 07:03

eatSleepCode


People also ask

How does Java handle exceptions in stream map?

Instead, you have three primary approaches: Add a try/catch block to the lambda expression. Create an extracted method, as in the unchecked example. Write a wrapper method that catches checked exceptions and rethrows them as unchecked.

Can we throw exception from stream in Java?

Unfortunately, we cannot do it in a Java stream because the map method accepts only a Function. We can create a bridge or conversion between these two types i.e., convert a ThrowingFunction into a Function using a simple utility method.

How do you catch exceptions on a stream?

In some way, we need to catch the exception to make the code compile. Naturally, we can do a simple try-catch inside the lambda and wrap the exception into a RuntimeException , as shown in the first example, but I think we can all agree that this is not the best way to go. . forEach(System.

How do you handle exceptions in parallel stream?

In that case, wrap the exception in a run time exception, and let the stream abort and throw it. Catch the wrapper exception, unwrap it and deal with it.


2 Answers

You could check if there's any element that passed your filter, and use Optional's orElseThrow to throw an exception if there isn't :

Integer match = 
    intList.stream()
           .filter(i -> i > 40)
           .findAny()
           .orElseThrow(...);

Of course, this will only give you one of the elements that pass the filter when the exception isn't thrown, so I'm not sure if it's exactly what you want.

like image 178
Eran Avatar answered Oct 05 '22 10:10

Eran


If you want to return the list if its size exceeds n elements, you might use the collectingAndThen collector:

List<Integer> list = 
    intList.stream()
           .filter(i -> i > 40)
           .collect(collectingAndThen(toList(), l -> { if (l.isEmpty()) throw new WhatEverRuntimeException(); return l;}));

However it might not be as readable as it gets, so you could simply add an if statement after collecting the results:

List<Integer> list = intList.stream().filter(i -> i > 40).collect(toList());
if (list.isEmpty()) {
    throw new WhatEverRuntimeException();
}

Finally, if the lower size limit is, let's say, 100, you might not want to build the list. In this case, you may use two stream pipelines, one to count the number of elements satisfying the lower bound you set, and one to actually build the list:

long count = intList.stream().filter(i -> i > 40).count();
if(count < limit) {
    throw new WhatEverRuntimeException();
}
List<Integer> list = intList.stream().filter(i -> i > 40).collect(toList());
like image 28
Alexis C. Avatar answered Oct 05 '22 10:10

Alexis C.