Dustin
Dustin

Reputation: 185

compareTo method needs some work

I need to sort cities and states into an arraylist in alphabetical order of cities, but if 2 cities have the same name the state will be the tiebreaker.

public class City implements Comparable  
{
   String name;
   String state;

   /**
   ** A constructor for the city and state.
   ** @param name the name of the city.
   ** @param state the name of the state.
   */   
   public City(String name, String state)
   {
      this.name = name;
      this.state = state;
   }
   //Gets the name and returns it.
   public String getName()
   {
      return name;
   }
   //Gets the state and returns it.
   public String getState()
   {
      return state;
   } 
   public int compareTo(Object otherCity)
   {
      City other = (City) otherCity;
      if (name.equals(other.name))
      {

      return name.compareTo(other.name);  
   }      
   public String toString()
   {
      return getClass().getName() + "[Name: " + name 
         + ", State: " + state + "]\n";
   }
} 

This is the portion of code I believe is where I should make the condition for the tiebreaker but i'm not sure how to code it.

public int compareTo(Object otherCity) {
   City other = (City) otherCity;
   if (name.equals(other.name)){

     return name.compareTo(other.name);  
   }
}

Any help would be greatly appreciated! Thanks!

Upvotes: 3

Views: 640

Answers (3)

Elliott Frisch
Elliott Frisch

Reputation: 201439

Comparable is generic, so I suggest you supply your type by implementing Comparable<City>

class City implements Comparable<City>

Then you can implement your comparison(s) with something like

@Override
public int compareTo(City other) {
    int r = this.name.compareTo(other.name);
    if (r != 0) {
        return r;
    } // the names are not the same, compare the states
    return this.state.compareTo(other.state);
}

or using the ternary

public int compareTo(City other) {
    int r = this.name.compareTo(other.name);
    // if (r != 0) then the names are not the same, compare the states
    return (r != 0) ? r : this.state.compareTo(other.state);
}

Also, since your fields do not have setters I suggest you mark them final so they are immutable

final String name;
final String state;

Upvotes: 5

You can tryout this. Here I consider the state value if two cities are equal.

public int compareTo(Object otherCity){
    City other = (City) otherCity;
    int iReturn = name.compareTo(other.name);
    if (iReturn == 0){
         //use your logic what to do when strings are equal. e.g.
         iReturn = iReturn = state.compareTo(other.state);
    }
    return iReturn;  
}

Upvotes: 2

Makoto
Makoto

Reputation: 106400

(I'm going to assume you went along with my suggestion in the comments and type-bound your Comparable.)

If the city name is equivalent, then the state is the tie-breaker. That's straightforward:

public int compareTo(@Nullable City otherCity) {
    if(null == otherCity) {
        return 1;
    }
    if(name.compareTo(otherCity.getName() == 0) {
        return state.compareTo(otherCity.getState());
    } else {
        return name.compareTo(otherCity.getName());
    }
}

There's an optimization in there in that you don't have to make two calls to getName, but this should give you the general idea. Further, you have setters/getters; your fields should be private.

Upvotes: 2

Related Questions