Search code examples
javalambdajava-stream

Java Lambda sort with object properties throws null pointer exception


  • Code when sorting with the Object property (which is another object), with null values though using he compartor nullsFirst() end up in null pointer exception.
import java.util.Comparator;
import java.util.stream.Collectors;
import java.util.List;
import java.util.ArrayList;

class HelloWorld {
    public static void main(String[] args) {
        AgeRange ageRange = new AgeRange();
        ageRange.setBegin(1);
        ageRange.setEnd(18);
        
        Person p1 = new Person();
        p1.setAgeRange(age);
        
        Person p2 = new Person();
        p2.setAgeRange(null);
        
        AgeRange ageRange1 = new AgeRange();
        ageRange1.setBegin(19);
        ageRange1.setEnd(25);
        
        Person p3 = new Person();
        p3.setAgeRange(ageRange1);
        
        List<Person> persons = new ArrayList<>();
        persons.add(p1);
        persons.add(p2);
        persons.add(p3);
        
        persons.stream().sorted(Comparator.nullsFirst(Comparator.comparing(Person::getAgeRange)))
        .collect(Collectors.toList());
        //above throws null pointer exception
        
    }
}

  class Person {
        private String name;
        private AgeRange ageRange;
        
        public String getName(){
            return this.name;
        }
        
        public void setName(String name){
            this.name = name;
        }
        
        public AgeRange getAgeRange(){
            return this.ageRange;
        }
        
        public void setAgeRange(AgeRange ageRange){
            this.ageRange = ageRange;
        }
        
    }
    
    class AgeRange implements Comparable<AgeRange>{
        long begin;
        long end;
        
        public void setBegin(long begin){
            this.begin = begin;
        }
        
         public void setEnd(long end){
            this.end = end;
        }
        
        public long getBegin(){
            return this.begin;
        }
        
        public long getEnd(){
            return this.end;
        }
        
        @Override
        public int compareTo(AgeRange obj){
            return Long.compare(begin,obj.begin);
        }
    }
  • exception
Exception in thread "main" java.lang.NullPointerException
at java.base/java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469)
at java.base/java.util.Comparators$NullComparator.compare(Comparators.java:83)
    at java.base/java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
    at java.base/java.util.TimSort.sort(TimSort.java:220)
    at java.base/java.util.Arrays.sort(Arrays.java:1515)
at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:353)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
    at HelloWorld.main(HelloWorld.java:34)

Understood that an operation done using the null object, is there way's to sort the null first in this approach.


Solution

  • You can try with this approach here:

    Here,

    I have passed the Comparator.nullsFirst in the Comparator.comparing() which will have the nulls value first and then compare the rest of the values ignoring the null data.

    You can also use Comparator.reverseOrder() if you want to have the reverse ordering of the data.

    List<Person> sortedData = persons.stream().sorted(Comparator.comparing(Person::getAgeRange,
      Comparator.nullsFirst(Comparator.naturalOrder())))
                .collect(Collectors.toList());
        System.out.println(sortedData);