Alex Rivera | Logout

In TreeSet, Sorting & Uniqueness of custom objects based on different properties

Asked 2010-12-15T06:58:41.097
13

Below is my Student class

class Student implements Comparable {
   String name;
   int rollNo;

   @Override
   public int compareTo(Object obj) {
        return ((Student)obj).name.compareTo(this.name);
   }
} 

latest modification: but still no getting the right result

@Override
public int compareTo(Object obj) {
    Student s = (Student) obj;
    if (name.equals(s.name)) { // achieving uniqueness
        return 0;
    } else {
        if (rollNo < s.rollNo) {
            return -1;
        } else if (rollNo > s.rollNo) {
            return 1;
        } else {
            // this makes `name` the second ordering option.
            // names don't equal here
            return name.compareTo(s.name);
        }
    }
}

If I create object of TreeSet<Student>, I am getting sorted list of Student objects based on unique name & ordered by name also.

But I need unique student-name in my TreeSet<Student> with order by student-rollNo.

Is it possible with Comparator? Can anybody help me, Every suggestion is appreciated. Thanks.

UPDATE: here is the complete program:

public class Student implements Comparable {

    int rollNo;
    String name;

    Student(String n,int rno) {
        rollNo=rno;
        name=n;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

        TreeSet<Student> ts = new TreeSet<Student>();
        ts.add(new Student("bbb",2));
        ts.add(new Student("aaa",4));
        ts.add(new Student("bbb",2));
        ts.add(new Student("ccc",3));
        ts.add(new Student("aaa",1));
        ts.add(new Student("bbb",2));
        ts.add(new Student("bbb",5));

        System.out.println(ts);

    }

    @Override
    public int compareTo(Object obj) {
        Student s = (Student) obj;
        if (name.equals(s.name)) { // achieving uniqueness
            return 0;
        }
Edit
Report

1 Answer

4

Ordering

The answer by @ralph on using a TreeSet with a specified comparator is a good one, use that.

Design

You should wrap your concept of a "student database" inside a class that exposes and documents the correct behaviors, rather than just using a raw collection. If obtaining lists of students in particular orders is a design requirement, expose methods (perhaps returning Iterable<Student> that say that. Behind the scenes, you can do a variety of things depending on the usage pattern:

  • Maintain one or more Sets and or Maps sorting/indexing students by fields of interest.
  • On-demand in-place array sort using Arrays.sort() and a specified Comparator.

Example....

final class StudentTable {
   private static final Comparator<Student> studentRollNoComparator = ...;
   private final SortedSet<Student> sortedByRollNo = 
      new TreeSet<Student>(studentRollNoComparator);

   public Iterable<Student> studentsOrderedByRollNo()
   {
      return sortedByRollNo;
   } 

   //see below
   public void addStudent(final Student foo) { ... }
}

Uniqueness

You need to override equals() and hashCode() on your Student class, to compare only the student name. Then you'll get uniqueness (silently) in your TreeSet. Obviously, if you do this, you need to code defensively to check to see if studentSet.contains(newStudent) before inserting newStudent, so you'll KNOW whether you've got a duplicate or not.

final class Student implements Comparable {
   ...

   @Override
   public boolean equals(Object o)
   {
      return o!=nu
answered 2010-12-16T14:39:08.933

Your Answer