0

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)

1
  • 1
    if you want to sort your student objects, the student class must implement the interface compareable: baeldung.com/java-comparator-comparable Commented May 2, 2021 at 6:54

2 Answers 2

2

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())
Sign up to request clarification or add additional context in comments.

Comments

1

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.