Dealing with a null attribute using java 8 streams and sorting using lambda expressions

20,602

Solution 1

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;

Solution 2

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.

Solution 3

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.

Solution 4

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

Solution 5

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());
Share:
20,602

Related videos on Youtube

Manu Joy
Author by

Manu Joy

Updated on January 25, 2020

Comments

  • Manu Joy
    Manu Joy over 4 years

    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?

    • Nir Alfasi
      Nir Alfasi almost 9 years
    • ajb
      ajb almost 9 years
      I'm unclear... is it e that is null, or e.getParentId()? If e.getParentId() is declared as an Integer (the boxed type), it may be null. But then when it's converted to an int to compare it to 100, the result will be a NullPointerException if it's null.

Related