Ankit Kadam
Ankit Kadam

Reputation: 105

Getting java.lang.ClassCastException: class lambda.Student cannot be cast to class java.lang.Comparable while using FlatMap

Getting java.lang.ClassCastException when stream.filter returns multiple resullts

package lambda;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

public class LambdaDemo {

    public static void main(String[] args) {
        List<Student> stList = new LinkedList<Student>();
        stList.add(new Student("Ankit", 22));
        stList.add(new Student("Soham", 32));
        stList.add(new Student("Nitin", 42));
        stList.add(new Student("Xoxo", 55));
        stList.add(new Student("Chetan", 62));

        Department scrDept = new Department("Science");
        scrDept.getStList().add(new Student("Ankit", 22));
        scrDept.getStList().add(new Student("Soham", 52));

        Department artDept = new Department("Arts");
        artDept.getStList().add(new Student("Xoxo", 42));
        artDept.getStList().add(new Student("Chetan", 92));

        List<Department> deptList = new ArrayList<Department>();
        deptList.add(scrDept);
        deptList.add(artDept);

        deptList.stream().flatMap(dept -> dept.getStList().stream())
                .forEach(employee -> System.out.println(employee.getName()));

        List<Student> orderedPassedStd = deptList.stream().flatMap(dept -> dept.getStList().stream())
                .filter(student -> student.getName().length() >= 4).sorted().collect(Collectors.toList());

        for (Student std : orderedPassedStd) {
            System.out.println(std.getName() + "  ---------  " + std.getMarks());
        }
    }

}

class Department {
    String deptName;
    List<Student> stList = new ArrayList<Student>();

    public Department(String deptName) {
        this.deptName = deptName;
    }

    public Department(String deptName, List<Student> stList) {
        this.deptName = deptName;
        this.stList = stList;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public List<Student> getStList() {
        return stList;
    }

    public void setStList(List<Student> stList) {
        this.stList = stList;
    }

}

class Student {

    String name;
    float marks;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public float getMarks() {
        return marks;
    }

    public void setMarks(float marks) {
        this.marks = marks;
    }

    public Student(String name, float marks) {
        this.name = name;
        this.marks = marks;
    }

}

Output : Ankit Soham Xoxo Chetan Exception in thread "main" java.lang.ClassCastException: class lambda.Student cannot be cast to class java.lang.Comparable (lambda.Student is in module javaMasterClass 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:1515) at java.base/java.util.ArrayList.sort(ArrayList.java:1750) at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:392) at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) 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 javaMasterClass/lambda.LambdaDemo.main(LambdaDemo.java:34)

Upvotes: 0

Views: 826

Answers (2)

katarina bosnjak
katarina bosnjak

Reputation: 11

sorted() method doc: https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#sorted--

It says that when an element is not Comparable that ClassCastException exception will be thrown.

You need to either make Student implement Comparable interface and implement method compareTo like this

class Student implements Comparable<Student>{

    String name;
    float marks;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public float getMarks() {
        return marks;
    }

    public void setMarks(float marks) {
        this.marks = marks;
    }

    public Student(String name, float marks) {
        this.name = name;
        this.marks = marks;
    }

    @Override
    public int compareTo(Student o) {
        var cmp = Float.compare(this.marks, o.marks);

        if(cmp != 0) return cmp;
        //TODO add this.name == null logic depending on needs
        return this.name.compareTo(o.name);

        //OR a one liner
        //return Comparator.comparing(Student::getMarks).thenComparing(Student::getName).compare(this, o);
    }
}

You can add any logic for comparing based on your needs. The convention is if this is > than o then compareTo returns integer > than 0, if they are equal 0 is returned, and if this is < than 0 , negative integer is returned. ( https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html )

Or you can call sorted with comparator argument Comparator.comparing(Student::getMarks).thenComparing(Student::getName) (once again you can put some other logic in here)

Upvotes: 1

Vicky Ajmera
Vicky Ajmera

Reputation: 796

At the place, where you're trying to sort the students, based on your sorting need, you can provide a comparator in the following way:

Update the line which contains .sorted() to,

If you want to sort Students based on Name,

.sorted(Comparator.comparing(Student::getName))

or

.sorted((s1, s2) -> s1.getName().compareTo(s2.getName()))

If you want to sort Students based on Marks,

.sorted(Comparator.comparing(Student::getMarks))

or

.sorted((s1, s2) -> Float.compare(s1.getMarks(), s2.getMarks()))

If you want to descending sorting on Student's Marks,

.sorted(Comparator.comparing(Student::getMarks).reversed())

Upvotes: 2

Related Questions