dedicatedtolearn
dedicatedtolearn

Reputation: 21

A compare function for sorting an array of objects in java?

I have an array of phonebook elements and I'm trying to sort them according to lexicographical order using comparable sort. But it all messes up. Please help. Thanks in advance

It will also help to describe about sort function in java a little bit! Here is the code:

package myphonebook;

import javax.swing.*;
import java.util.Arrays;
import java.util.Comparator;
public class MyPhoneBook implements Comparator<MyPhoneBook>{

    private String name,email,number;
    MyPhoneBook()
    {
    }

    public void input()
    {
        name = (JOptionPane.showInputDialog("Enter Name:\n")).toString();
        number = JOptionPane.showInputDialog("Enter Number:\n").toString();
        email = JOptionPane.showInputDialog("Enter email:\n").toString();
    }
    public void print()
    {
        JOptionPane.showMessageDialog(null, "Name: " + name+ "\n" + "Phone: " +number          +"\n"     +       "Email: " + email);
    }

    public static void main(String[] args) {
        MyPhoneBook a[] = new MyPhoneBook[300];
        MyPhoneBook b = new MyPhoneBook();
        //final Integer[] sorted = ArrayUtils.toObject(MyPhoneBook);
        int i,n;
        n = Integer.parseInt(JOptionPane.showInputDi… total number:\n"));
        for(i=0;i<n;i++)
        {
            a[i] = new MyPhoneBook();
            a[i].input();
        }
        Arrays.sort(a);
        for(i=0;i<n;i++)
        {
            a[i].print();
        }
    }

    @Override
    public int compare(MyPhoneBook o1, MyPhoneBook o2) {
        return o1.number.compareTo(o2.number);
    }

    public int compareTo(MyPhoneBook o) {
        if(this.name.equals(o.name)) return this.number.compareTo(o.number);
        if(this.number.equals(o.number)) return this.email.compareTo(o.email);
        if(this.email.equals(o.email)) return this.name.compareTo(o.name);
        return 0;
    }
}

Upvotes: 0

Views: 1988

Answers (3)

Subhrajyoti Majumder
Subhrajyoti Majumder

Reputation: 41210

Just use String#compareTo, it compares two strings lexicographically. The comparison is based on the Unicode value of each character in the strings.

public class MyPhoneBook implements Comparable<MyPhoneBook>{
    @Override
    public int compareTo(MyPhoneBook o) {
            int returnValue =0;
            if(o!=null){
                  returnvalue = this.name.compareTo(o.name);
                  if(returnValue==0){
                       returnValue = this.number.compareTo(o.number);
                       if(returnValue==0){
                              returnValue = this.email.compareTo(o.email);
                      }
                  }

            }
            return returnValue;
        }
}

Upvotes: 1

A4L
A4L

Reputation: 17595

When running the code as you posted it it comes to a

Exception in thread "main" java.lang.ClassCastException: ...
MyPhoneBook cannot be cast to java.lang.Comparable

This is because you call

Arrays.sort(a);

Arrays.html#sort expects the Objects contained in the array to be implementing the interface Comparable. Your class is implmenting Comparator though.

You should change your class declaration to one of the following

public class MyPhoneBook implements Comparable<MyPhoneBook> {

and just remove

@Override
public int compare(MyPhoneBook o1, MyPhoneBook o2) {
    return o1.number.compareTo(o2.number);
}

Or

public class MyPhoneBook {

and the call of sort to

Arrays.sort(a, new Comparator<MyPhoneBook>() {
    @Override
    public int compare(MyPhoneBook o1, MyPhoneBook o2) {
        // TODO implment here your comapre logic
        return o1.number.compareTo(o2.number);
    }
});

After you have fixed that you'll get NullPointerException, againt because of the line

Arrays.sort(a);

This is because you pass an array of the length 300 and you do not necessarily have to put all 300 element in it since you ask for total number

you should be using

Arrays.sort(a, 0, n);

This sorts only the range witch have data. See the javadoc.

Upvotes: 0

Michael Aaron Safyan
Michael Aaron Safyan

Reputation: 95519

There are several problems here: the first is that your comparison is not actually lexicographic. For example, when the names are equal, you completely ignore the email address in your comparison logic. The second problem is that you fail to specify the comparator as a parameter to Arrays.sort().

First problem: fix comparison logic

If you can use third-party libraries in your code, then a really neat and simple way to handle this is using the ComparisonChain class from the Guava libraries (Google's core Java libraries that are opensource):

public int compareTo(MyPhoneBook o) {
  return ComparisonChain
      .start()
      .compare(name, o.name)
      .compare(email, o.email)
      .compare(number, o.number)
      .result();
 }

Assuming you can't do that, however, here's the right way to do it:

public int compareTo(MyPhoneBook o) {
   int nameComparison = name.compareTo(o.name);
   if (nameComparison != 0) {
     return nameComparison;
   }
   int emailComparison = email.compareTo(o.email);
   if (emailComparison != 0) {
     return emailComparison;
   }
   return number.compareTo(o.number);
}

Second problem: invoke Arrays.sort() with the comparator

Instead of your current call to Arrays.sort(), use:

Arrays.sort(a, new PhoneBookComparator());

And define PhoneBookComparator as a separate Comparator class.

Upvotes: 1

Related Questions