Handling Null Objects and Throwing Exceptions in Threads

Consider the Parent class, which contains only one Integer attribute. I created 6 objects of the parent class and one object was null. Then I added these objects to the list.

I want to get the corresponding object by the value of the Integer attribute. I used Java 8 threads for this.

 Predicate<Parent> predicate = e -> e.getId() == 100; // sample attribute value result = list.stream().filter(predicate).collect(Collectors.toList()); 

But I got a NullPointerException , so I edited the code:

 list.stream().filter(h -> h!=null).filter(predicate).collect(Collectors.toList()); 

But I want to throw an exception if any of the objects is null. If no object in the list is null, I want to get the corresponding object from the list.

How can I achieve this using a single statement using Java 8 threads?

+7
java lambda java-8
source share
3 answers

JB Nizet's answer is fine, but it uses map only for its side effects, and not for the map operation, which is rather strange. There is a method that you can use when you are only interested in the side effects of something, for example, throwing an exception: peek .

 List<Parent> filtered = list.stream() .peek(Objects::requireNonNull) .filter(predicate) .collect(Collectors.toList()); 

And if you want your own exception to just put lambda there:

 List<Parent> filtered = list.stream() .peek(p -> { if (p == null) throw new MyException(); }) .filter(predicate) .collect(Collectors.toList()); 

Checked Exceptions

If your exception is checked, you can either check zero in advance, if you don't mind going to the list twice. This is probably best in your case, but may not always be possible.

 if (list.contains(null)) throw new MyCheckedException(); 

You can also throw the thrown exception into the stream pipeline, catch it, and then throw the checked flag:

 try { ... .peek(p -> { if (p == null) throw new MyException(); }) ... } catch (MyException exc) { throw new MyCheckedException(); } 

Sneaky throw

Or you can take an elegant but controversial road and use the covert throw method.

But be careful! This method bypasses the proven exception system and you should know what you are doing. Be sure to declare that the surrounding method throws a MyCheckedException ! The compiler will not warn you if you do not, and this will most likely cause strange errors if exceptions are noted, if they are not expected.

 @SuppressWarnings("unchecked") public <T extends Throwable> void throwSneakily(Throwable t) throws T { throw (T) t; } public void m() throws MyCheckedException { List<Parent> filtered = list.stream() .peek(p -> { if (p == null) throwSneakily(new MyCheckedException()); }) .filter(predicate) .collect(Collectors.toList()); } 
+10
source share

Let's start with the simplest solution:

 if(list.contains(null)) throw new MyException(); result = list.stream().filter(predicate).collect(Collectors.toList()); 

If you suspect that the list contains null and even has a special type of exception to flag this condition, a preliminary check is the cleanest solution. This ensures that such a condition does not remain silent if the predicate changes to something that can handle null , or when you use a short-circuit operation that can end before it encounters the next null .

If the appearance of null in the list is still considered a programming error that should not happen, but you just want to change the type of exception (I cannot imagine the real reason for this), you can just catch and throw the exception:

 try { result = list.stream().filter(predicate).collect(Collectors.toList()); } catch(NullPointerException ex) { if(list.contains(null)) // ensure that we don't hide another programming error throw new MyException(); else throw ex; } 

This works effectively under the assumption that null references do not occur. As said, if you suspect the list is null , you should prefer a preliminary check.

+3
source share
 Function<Parent, Parent> throwingIdentity = p -> { if (p == null) { throw new MyException(); } return p; }; List<Parent> filtered = list.stream() .map(throwingIdentity) .filter(predicate) .collect(Collectors.toList()); 
+1
source share

All Articles