Home > Net >  Why get class cannot be cast to class java.lang.Comparable
Why get class cannot be cast to class java.lang.Comparable

Time:06-14

I'm iterating all Student data using natural sorting method of java 8 sorted(). While iterating student data, get exception in IDE console class com.java8.Student cannot be cast to class java.lang.Comparable. My StreamStudent.java file is inside com.java8 package.

Here is my full stack trace:

Exception in thread "main" java.lang.ClassCastException: class com.java8.Student cannot be cast to class java.lang.Comparable (com.java8.Student is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap')
    at java.base/java.util.Comparators$NaturalOrderComparator.compare(Comparators.java:47)
    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:1307)
    at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:353)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
    at com.java8.StreamStudent.main(StreamStudent.java:72)

Here down is my code:

package com.java8;

import java.util.*;
import java.util.stream.*;

class Student{
    String firstName;
    String lastName;
    Integer groupId;
    Integer age;

    // constructor and getter, setter

}

public class StreamStudent {
    public static void main(String[] args) {
        List<Student> stdList = new ArrayList<>();
        stdList.add(new Student("Sara", "Mills", 1, 18));
        stdList.add(new Student("Andrew", "Gibson", 2, 21));
        stdList.add(new Student("Craig", "Ellis", 1, 23));
        stdList.add(new Student("Steven", "Cole", 2, 19));
        stdList.add(new Student("Andrew", "Carter", 2, 2));

        
        System.out.println("1. Sort all student firstname by name");
        List<Student> students =  stdList.stream().sorted().collect(Collectors.toList());
        students.forEach((s) -> System.out.println(s.getFirstName()   " "   s.getLastName()   " "   s.getGroupId()   " "   s.getAge()));
    }
}

CodePudding user response:

Student must implement Comparable. The implementation of Comparable is what defines the natural ordering.

This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred to as its natural comparison method.

public class Student implements Comparable<Student> {

  @Override
  public int compareTo(Student o) {
    //implement comparison here
    return 0;
  }
}

CodePudding user response:

The elements of your stream must implement the Comparable interface in order to be sorted via the sorted() stream operation. Alternatively, if you cannot change the implementation of the Student class, you can supply a Comparator instance to the overloaded version sorted(Comparator<? super T> comparator). This way you can still sort your elements without having to change the Student's implementation.

https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#sorted-java.util.Comparator-

Student Implementing Comparable

class Student implements Comparable<Student> {
    String firstName;
    String lastName;
    Integer groupId;
    Integer age;

    // constructor and getter, setter

    @Override
    public int compareTo(Student o) {
        return Comparator.comparing(Student::getFirstName).thenComparing(Student::getLastName).compare(this, o);
    }
}

public class StreamStudent {
    public static void main(String[] args) {
        // ... same code of yours ...

        List<Student> students =  stdList.stream().sorted().collect(Collectors.toList());

        // ... same code of yours ...
    }
}

Supply a Comparator to sorted

public class StreamStudent {
    public static void main(String[] args) {
        // ... same code of yours ...

        List<Student> students =  stdList.stream().sorted(Comparator.comparing(Student::getFirstName).thenComparing(Student::getLastName)).collect(Collectors.toList());

        // ... same code of yours ...
    }
}     

CodePudding user response:

Your student class should implement Comparable interface so it can be sorted:

class Student implements Comparable<Student> {
    String firstName;
    String lastName;
    Integer groupId;
    Integer age;

    @Override
    public int compareTo(Student o) {
        return this.firstName.compareTo(o.firstName);

        //In case you want compare based on multiple fields
        /*
        return Comparator
              .comparing((Student s)->s.lastName)
              .thenComparing(s->s.firstName)
              .compare(this, o);
       */
    }
}

Another solution is implementing Comparator interface for class and passing it as input to sorted method, This is useful in cases that you want sort bases on different fields in different sitations:

Comparator<Student> studentComparator
        = Comparator.comparing(Student::getLastName).thenComparing(Student::getFirstName);

List<Student> studentsSorted =  stdList.stream().sorted(studentComparator).collect(Collectors.toList());

CodePudding user response:

You need to implement Comparable. Here a link that might help you. You have to implement the method compareTo

  • Related