0

I know basic programming but I'm new to OOP and Java. I'm trying to short and search ArrayList of objects. I know there are many ways to do it but I like two-approach here with collections, Java List.contains(Object with field value equal to x) and here Sort ArrayList of custom Objects by property codes are working when they are inside the main class but I wanted to move them in student class and calling over my own sort and search methods. The sort function still works but the search returns wrong index integers. I couldn't find what I m missing. The complete code is below.

  /* implementation of binary search found at
https://stackoverflow.com/questions/18852059/
and sort solution at
https://stackoverflow.com/questions/2784514/
 */

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;

public class test {
    static ArrayList<Student> course = new ArrayList<>();

    public static void main(String[] args) {
        System.out.print("Enter name to search: ");
        Scanner input = new Scanner(System.in);
        String stName = input.nextLine();

        course.add(new Student("will", 353429, 13.2));
        course.add(new Student("joe", 353430, 12.1));
        course.add(new Student("bill", 353431, 14.9));
        course.add(new Student("jim", 353432, 15.3));
        course.add(new Student("jack", 353473, 11.2));
        course.add(new Student("jean", 353439, 16.8));
        course.add(new Student("jill", 353333, 14.9));
        course.add(new Student("jane", 353432, 15.7));
        course.add(new Student("john", 353421, 10.6));
        course.add(new Student("ben", 353438, 16.0));
        course.add(new Student("dave", 353529, 14.9));
        course.add(new Student("jim", 352989, 15.3));
        course.add(new Student("doug", 353178, 11.2));

        sortStudents();

/*  // search part works when its here , inside main class
        int idx = Collections.binarySearch(course, new Student( stName ), new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
*/

        int idx = searchStudent( stName );

        System.out.println("Sorted list");
        for (int cnt=0;cnt<course.size();cnt++){
            System.out.println(cnt + " "+ course.get(cnt).toString());
        }

        if (idx>0){
            System.out.println(stName +" found on line: " + idx);
            }else{
            System.out.println(" Not in the list" +idx);
        }
    }

    static void sortStudents(){
        Collections.sort(course,Student.sortByName);
    }

    static int searchStudent(String nm){
        return Collections.binarySearch(course, new Student(nm));
    }


    static  class Student implements Comparable<Student>{
        private String name;
        private int age;
        private double points;

        public Student(String nm) {  this.name = nm; } // constructor

        public Student(String nm, int n, double p) {  // constructor
            this.name = nm;
            this.age = n;
            this.points = p;  }

        public String getName(){ return name; }
// but search code fails when moved here 
        public static Comparator<Student> binarySearch = new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getName().compareTo(o2.getName());
            }
        };

        public static Comparator<Student> sortByName = new Comparator<Student>() {
            @Override
            public int compare(Student obj1, Student obj2) {
                //sort in ascending order
                return obj1.name.compareTo(obj2.name);
                //sort in descending order
                //return obj2.name.compareTo(obj1.name);
            }
        };

        @Override
        public int compareTo(Student o) {
            return 0;
        }

        
        @Override
        public String toString() {
            return "Name:" + name + ", Age:" + age;
        }
    }
}


  

1 Answers1

2

Problem

That's because of your compareTo, because you didn't implement how may be compared the Student between them, you only implemented a name comparator, and this is used by the Collections.binarySearch

@Override
public int compareTo(Student o) {
    return 0;
}

You could fix with explicit Comparator

static int searchStudent(String nm) {
    return Collections.binarySearch(course, new Student(nm), Student.sortByName);
}

Improve

Also Comparator<Student> binarySearch is same as Comparator<Student> sortByName, no reason to get 2 things doing same.

You need to understand that, either

  • you need to a Comparator to tell how to order objects
  • make the object Comparable so it knows ITSELF how to order it with the others

Here you did both, that isn't useful, remove the Comparators definitions


Fix

So only a compareTo method will do the job

@Override
public int compareTo(Student o) {
    int diff = this.name.compareTo(o.name);
    if (diff != 0) {
        return diff;
    }
    return Integer.compare(this.age, o.age);
}

It can be simplified with a Comparator that allows some method chaining. Note that it is private, it shouldn't be used outside the class manually, AS the class now knows by itself how to order elements

static private Comparator<Student> studComp = Comparator.comparing(Student::getName)
                                                    .thenComparing(Student::getAge);

@Override
public int compareTo(Student o) {
    return studComp.compare(this, o);
}

Giving in the main class

static void sortStudents() {
    course.sort(Comparator.naturalOrder());
}

static int searchStudent(String nm) {
    return Collections.binarySearch(course, new Student(nm));
}
azro
  • 53,056
  • 7
  • 34
  • 70