0

I have an ArrayList that holds 2 types of objects in it (objects from class Student and objects from class Teacher).

My question is how can I sort it so that all objects that are from Student to appear first and then all objects that are from class Teacher to appear after them.

For example: Student1, Student2, Student3, Teacher1,Teacher2,Teacher3

Here is my code:

public ArrayList sortList(){

    ArrayList<Student> students = new  ArrayList<Student>();
    ArrayList<Teacher> teachers = new  ArrayList<Teacher>();
    ArrayList<Person> university = new  ArrayList<Person>();
    for(Person p : list){
        if(p.getClass().getSimpleName().equals("Teacher")){
            teachers.add((Teacher)p);
        };
        if(p.getClass().getSimpleName().equals("Student")){
            students.add((Student)p);
        }
        university.addAll(students);
        university.addAll(teachers);
    }
    return university;
}
5
  • 1
    Did you read about "Comparable" in java? Commented Mar 13, 2017 at 10:26
  • 4
    While we don't know the context, I would like to generally advice to just keep students and teachers in two separate ArrayLists. We all know that having both in the same class room is already problematic, but the same ArrayList? Oh boy. Commented Mar 13, 2017 at 10:26
  • Well, dirty solution might be to run for loop and check with instanceof keyword. Commented Mar 13, 2017 at 10:28
  • If you really need to have them both in one list, then you can separate into two list sort each list, and then append one list to the other Commented Mar 13, 2017 at 10:30
  • Read up comparator and comparable. Commented Mar 13, 2017 at 10:32

6 Answers 6

4

You can use Collections.sort(list,comparator)

In the Comparator you can compare the class names because (luckily) S is before T in the alphabet:

   List<Object> studentsAndTeachers = // ...
   Collections.sort(studentsAndTeachers, (o1, o2) -> o1.getClass().getName().compareTo(o2.getClass().getName()));

of cause you ave to apply other sorting criteria first or extend the comparator to recognize them...

Sign up to request clarification or add additional context in comments.

Comments

1

You can use Comparator.comparing for that:

list.sort(Comparator.comparing(Teacher.class::isInstance))

This works because Class.isInstance returns boolean which is wrapped into Boolean which implements Comparable.

1 Comment

Or, if you want to sort on class name: Collections.sort(list, Comparator.comparing(o -> o.getClass().getName()))
0

Sorting like this will do the job for you, although is not a quite good solution generally speaking.

Collections.sort(classroom, (o1, o2) -> {
    if (o1 instanceof Student && o2 instanceof Teacher) {
        return -1;
    }

    if (o1 instanceof Teacher && o2 instanceof Student) {
        return 1;
    }

    return 0;
});

Comments

0

Now it should work like a bread with butter:

public class Main
{
    public static void main(String[] args)
    {
        List<Human> humans = new ArrayList<>();
        humans.add(new Teacher("Teacher1"));
        humans.add(new Teacher("Teacher2"));
        humans.add(new Student("Student3"));
        humans.add(new Student("Student1"));
        humans.add(new Teacher("Teacher3"));
        humans.add(new Student("Student2"));

        Collections.sort(humans, new Comparator<Human>()
        {
            @Override
            public int compare(Human o1, Human o2)
            {
                if (o2 instanceof Teacher) {
                    return -1;
                } else if (o1 instanceof Teacher && o2 instanceof Student) {
                    return 1;
                }
                /* other checks not about being teacher or student goes here... */                
            }
        });
        System.out.println(humans);
    }
}

interface Human
{
    String getName();

    void setName(String name);
}

class Teacher implements Human
{
    private String name;

    public Teacher(String name)
    {
        super();
        this.name = name;
    }

    @Override
    public String getName()
    {
        return name;
    }

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

class Student implements Human
{
    private String name;

    public Student(String name)
    {
        super();
        this.name = name;
    }

    @Override
    public String getName()
    {
        return name;
    }

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

1 Comment

The comparable interface should maintain the natural order of object of a class. My feeling is that being Teacher or Student is not the natural order of persons (at least not in that order... ;o) )
0

Here's a Comparator class that orders Human objects based on class name, and then the value of the name attribute.

    public class Comparator<Human> {
        public int compare(Human h1, Human h2) {
            int res = h1.getClass().getName().compareTo(
                         h2.getClass().getName());
            if (res == 0) {
                res = h1.getName().compareTo(h2.getName());
            }
            return res;
        }
    }

If you use this with Collections.sort(...), you can sort the list into the required order.

Note that this implementation:

  • sorts objects with the same type based on their name (as implied by the example), and
  • doesn't break if you add more subclasses of Human.

Comments

0

You can use Comparator.comparing along with listName.sort() like below;

list.sort(Comparator.comparing(o -> o.getClass().getName()));

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.