Let's consider a Parent
class which contains only one Integer
attribute. I created 6 objects of parent class and values of attribute are 100, 20, 300, 400, 500, null
.
Now I added all the objects to a list(Name of list is list). Then I want to get the objects whose attribute value is greater than 100
. I used Java 8 streams for this purpose.
Predicate<Entity> predicate = e -> e.getParentId() < 100;
result = list.stream().filter(predicate).collect(Collectors.toList());
I also want to sort the list in descending order. I used the following code for this purpose.
Comparator<Entity> comp = (d1,d2) -> d2.getId().compareTo(d1.getId());
list.sort(comp);
In both cases I get a NullPointerException
.
How to handle this?
All of the answers here revolve around "throw out the bad elements, those that have a null getParentId()
." That may be the answer, if they are indeed bad. But there's another alternative: Comparators.nullsFirst
(or last.) This allows you to compare things treating a null value as being less than (or greater than) all non-null values, so you don't have to throw the elements with a null parentId away.
Comparator<Entity> cmp = nullsLast(comparing(Entity::getParentId));
List<Entity> list = list.stream().sorted(cmp).collect(toList());
You can do a similar thing for filtering; define your predicate as:
Predicate<Entity> predicate = e -> e.getParentId() != null
&& e.getParentId() < 100;
Looks like you are looking for something like:
list.sort(Comparator.comparing(Entity::getParent,
Comparator.nullsLast(Integer::compareTo)));
All the elements with parent null will be put at the end and the rest will be sorted by their parent.
Try pre-filtering for non-null parentId
values only:
result = list.stream().filter(e -> e.getParentId() != null).filter(predicate).collect(Collectors.toList());
[edit] Just saw, that the attribute ( e.parentId
) seems the one being null
. In that case, the second thing, the sorting, breaks. You are sorting the original list, not the filtered one. Try result.sort(comp)
, then you should avoid the NPE.
You can do it all in one Stream pipeline :
List<Entity> result =
list.stream()
.filter(e -> e.getParentId()!=null) // it's not clear if the null
// is the Entity object itself
// (in which case it should be e!=null)
// or just the ParentId member
.filter(predicate)
.sorted(comp)
.collect(Collectors.toList());
BTW, according to the text of your question, the original predicate should be :
Predicate<Entity> predicate = e -> e.getParentId() > 100; // not < 100
Harness the power of a method reference to make the code even more compact:
List<Entity> result =
list.stream()
.filter(Objects::nonNull)
.filter(predicate)
.sorted(comp)
.collect(Collectors.toList());
You can do:
Predicate<Entity> predicate = e -> e.getParentId() < 100;
Predicate<Entity> nonNull = e -> e != null;
result = list.stream().filter(nonNull)
.filter(predicate)
.collect(Collectors.toList());
Of course, you could combine the predicates into one, but I introduced a second one for better readability. Also, you're free to change the nonNull
predicate to check either the whole entity, or just the id
attribute (or even both). Just play a bit with it. :)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.