1

I’m trying to create a custom comparison for my list of objects implementing the comparable interface.

With one level of comparison, it’s an ordinary task, but this time things are a little more complicated.

Let me present you the details, I have a list of the following objects:

 Person { 
String name;
String gender;
int age;
}

The first thing I need to do is to compare by name (simple to do), but when I have the same name, I need to compare by age.

Please would you like to help to solve this issue?

henri Dunand
  • 45
  • 1
  • 1
  • 4
  • In override compareTo method, you may use `if` statement for comparing the ages if names are same. – Mustafa Çil Mar 27 '17 at 19:30
  • 1
    _"The first thing I need to do is to compare by name (simple to do), but when I have the same name, I need to compare by age."_ -- That is a good pseudocode version of what you should code. What's stopping you? – Jim Garrison Mar 27 '17 at 19:31
  • 1
    `int r = this.name.compareTo(that.name); if (r != 0) return r; return Integer.compare(this.age, that.age);` – Elliott Frisch Mar 27 '17 at 19:31

3 Answers3

2

Even though I suspect this is a homework question, I'll help you out and teach you along the way.

Class Person implements Comparable<Person>{ 
    String name;
    String gender;
    int age;

    @override
    int compareTo( Person p2 ){
        if (this.name.equals(p2.name)) return 0;
        else return Integer.compare(this.age,p2.age);
}

What we are doing here:

  1. Implement the Comparable interface on your Person class. The type parameter that we are looking here is Person, since you are going to be comparing a person with another person. This allows us to...
  2. Override the Comparable.compareTo() method with our own implementation.
  3. Compare names with string.equals(), be careful never to use == for string equality
  4. Compare age if names are not the same. Since you are using a primitive datatype you must use Integer.compare, which is one of the few ways to compare a primitive int.

A note, you can further override Object.equals() to take a Person object and compare object equality on person, or you can just set it to this.compareTo(p2) == 0, as compareTo() SHOULD return 0 if objects are equal. This is not how you have your implementation and you are technically breaking the contract of the Comparable interface.

Good luck with your homework.

Community
  • 1
  • 1
TTT
  • 1,952
  • 18
  • 33
0
int compareTo( Person right ) {
   int r = this.name.compareTo( right.name );
   if( r == 0 )  {
      r = Integer.compare( this.age, right.age );
   }
   return r;
}
Aubin
  • 14,617
  • 9
  • 61
  • 84
0

I know this is a much longer solution but counterbalancing it somewhat flexible then just this:

public class Person
{
  int compareTo( Person p )
  {
    int retValue = first_name.compareTo( p.first_name );
    if( retValue == 0 )
    {
      int retValue = last_name.compareTo( p.larst_name );
      if ( retValue == 0 )
        retValue = Integer.compare( age, p.age );
      return retValue;
    }
  }
}

I created a Person specific comparator class with a mode field (which field of the Person should be compared). If its result is zero it calls its subComparator (if there is one). In this way the caller (main function) decides the ordering mode (how the comparators nest together) and the orderind direction:

The Person class:

public class Person
{
  public String first_name;
  public String last_name;
  public int age;

  public Person( String first_name_, String last_name_, int age_ )
  {
    super();
    first_name = first_name_;
    last_name = last_name_;
    age = age_;
  }
}

The PersonComparator class:

public class PersonComparator implements Comparator<Person>
{
  public static final int COMPARE_BY_FIRSTNAME = 0;
  public static final int COMPARE_BY_LASTNAME = 1;
  public static final int COMPARE_BY_AGE = 2;

  int mode;
  boolean desc;
  private final Comparator<Person> subComparator;


  public PersonComparator( int mode_, Comparator<Person> subComparator_ )
  {
    super();
    mode = mode_;
    subComparator = subComparator_;
  }

  public PersonComparator( int mode_, Comparator<Person> subComparator_, boolean desc_ )
  {
    super();
    mode = mode_;
    desc = desc_;
    subComparator = subComparator_;
  }

  @Override
  public int compare( Person p1, Person p2 )
  {
    int retValue = 0;
    switch ( mode )
    {
      case PersonComparator.COMPARE_BY_FIRSTNAME:
        {
          retValue = compareByFirstName( p1, p2 );
          break;
        }
      case PersonComparator.COMPARE_BY_LASTNAME:
        {
          retValue = compareByLastName( p1, p2 );
          break;
        }
      case PersonComparator.COMPARE_BY_AGE:
        {
          retValue = compareByAge( p1, p2 );
          break;
        }
    }
    if ( desc )
      return -retValue;
    else
      return retValue;
  }

  protected int compareByFirstName( Person p1, Person p2 )
  {
    int retValue = p1.first_name.compareTo( p2.first_name );
    if ( retValue == 0 )
      if ( subComparator != null )
        retValue = subComparator.compare( p1, p2 );
      else
        retValue = 0;
    return retValue;
  }

  protected int compareByLastName( Person p1, Person p2 )
  {
    int retValue = p1.last_name.compareTo( p2.last_name );
    if ( retValue == 0 )
      if ( subComparator != null )
        retValue = subComparator.compare( p1, p2 );
      else
        retValue = 0;
    return retValue;
  }

  protected int compareByAge( Person p1, Person p2 )
  {
    int retValue = p1.age - p2.age;
    if ( retValue == 0 )
      if ( subComparator != null )
        retValue = subComparator.compare( p1, p2 );
    return retValue;
  }
}

The caller:

public class PersonComparatorApp
{
  public static void main( String[] args )
  {
    List<Person> l = new ArrayList<>();
    l.add( new Person( "b", "c", 1 ) );
    l.add( new Person( "b", "b", 1 ) );
    l.add( new Person( "b", "b", 2 ) );
    l.add( new Person( "b", "b", 1 ) );
    l.add( new Person( "b", "a", 1 ) );
    l.add( new Person( "c", "b", 1 ) );
    l.add( new Person( "a", "b", 1 ) );
    l.add( new Person( "a", "a", 1 ) );

    PersonComparator pcAge = new PersonComparator( PersonComparator.COMPARE_BY_AGE, null );
    PersonComparator pcLastName = new PersonComparator( PersonComparator.COMPARE_BY_LASTNAME, pcAge );
    PersonComparator pcFirstName = new PersonComparator( PersonComparator.COMPARE_BY_FIRSTNAME, pcLastName );
    l.sort(pcFirstName);
    for ( Person p : l )
      System.out.println( p.first_name + " " + p.last_name + " " + p.age );
  }
}
The Bitman
  • 1,279
  • 1
  • 11
  • 25