Have a look at the following snippet that tries to convert a list of strings into a list of class objects:
public static List<Class<?>> f1(String... strings) {
return
Stream.of(strings)
.map(s -> {
try {
return Class.forName(s);
}
catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
}
return null;
})
.collect(Collectors.toList());
}
Because of the way Java handles checked exceptions in streams (as has been discussed at length here - where I also blatantly stole my example snippet from), you have to have the additional return statement after the try-catch block. This will result in an unwanted null reference being added to the result of type List<Class>.
To avoid this extra null reference, I came up with the following function, achieving a better result with a plain old procedural loop:
public static List<Class<?>> f2(String... strings) {
List<Class<?>> classes = new ArrayList<>();
for (String s : strings) {
try {
classes.add(Class.forName(s));
}
catch (ClassNotFoundException e) {
// Handle exception here
}
}
return classes;
}
Does this observation allow me to draw a conclusion in the form of a best-practice advice, that could be expressed like the following?
If you need to call a function that throws an exception inside a stream and you cannot make use of stream.parallel()
, better use a loop, because:
You'll need the try-catch block anyway (notwithstanding the tricky solutions involving some kind of wrapper around the throwing function provided in the aforementioned discussion)
Your code will not be less concise (mainly because of 1.)
Your loop will not break in case of an exception
What do you think?