How to compare objects in a generic LinkedList

2k Views Asked by At

How do you compare objects in a generic Linked List? I wrote my linked list from scratch. I have a class called Country that reads from a csv file and stores the name of country with its cellular stat data for a particular year. It reads dat from the year 1960 to 2012. My program works fine as i am able to print out the list. But when i search the list to match a country name that was printed out in the console. It says it wasn't found. I am new to generics, and i feel there something wrong as i tried to override the equals method in the class Country to compare the names. But my equals method in class Country is not been called. I tried debugging the equals method to see if it was ever called by placing a print out statement but it was never called. My guess is because of using the generics. Please i need some help to solve this issue. This is one issue i am having with the application as my contains method is not comparing the country names at all.

class linked list

public class LinkedList<T> {

private Node<T> first;

public LinkedList()
{
    this.first = null;
}

//returns true if list is empty
public boolean isEmpty()
{
    return (first==null);
}
//adds the node to the end of the list
public void add(T obj)
{
    Node<T> newNode = new Node<T>(obj);
    if(this.isEmpty())
    {
        newNode.setNode(first);
        first = newNode;
    }
    else
    {
        Node<T> current = first;
        while(current.getNext()!=null)
        {
            current = current.getNext();
        }
        current.setNode(newNode);
    }
}

public String toString()
{
    String result ="";
    if(this.isEmpty())
    {
        result += "Cannot print an empty list";
        return result;
    }
    else
    {
        Node<T> current = first;
        while(current!=null)
        {
            result +=current.getObj();
            current = current.getNext();
        }
        return result;
    }
}
//searches for the countryName and returns the country if found
public T contains(T obj)
{
    if(this.isEmpty())
    {
        return null;
    }
    else
    {
        Node<T> current = first;
        while(current!=null)
        {
            if(current.getObj().equals(obj))
            {
                return current.getObj();
            }
            current= current.getNext();
        }
        return null;
    }
}
}

class Node:

public class Node<T> {

private T data;
private Node<T> next;

public Node(T data)
{
    this.data = data;
    this.next = null;
}

public Node(T data, Node<T> next)
{
    this.data = data;
    this.next = next;
}

public void setNode(Node<T> next)
{
    this.next = next;
}

public Node<T> getNext()
{
    return this.next;
}

public T getObj()
{
    return data;
}

  }

class Country: has the override method equals

public class Country  {

private String countryNames;
private SubscriptionYear[] subscriptions;
private int size;
private int location;

public Country(String country)
{
    this.countryNames = country;
}
public Country(String country, int arraylength)
{
    this.countryNames = country;
    this.size = arraylength;
    subscriptions = new SubscriptionYear[size];
    location = 0;
}
//adds the subscription.
public void addSubscriptionYear(int year, double subscription)
{
        subscriptions[location]= new SubscriptionYear(year, subscription);
        ++location;
}

//overrides the toString method and prints out the countries.
public String toString()
{
    System.out.print(countryNames+"\t");
    for(SubscriptionYear s: subscriptions)
    {
        //System.out.print(countryNames+"\t");
        System.out.print(s.getSubscription()+"\t");
    }
    System.out.println();
    return  "";
}
//returns countryName
 public String getName()
 {
    return this.countryNames;
 }
//overrides the equals method and returns country name if found
public boolean equals(Country obj)
{
    System.out.println("In the equals method");
    return this.countryNames.equalsIgnoreCase(obj.countryNames);
}

}

method in main that calls the function to compare the name of country in the node.

private void testRandomListOfCountries(Country [] allCountries)
{   
    Scanner keyboard = new Scanner(System.in);
    System.out.println("How many countries do you want to add to the list?");
    int requestedSize = Integer.parseInt(keyboard.nextLine());


    // Build the list out of a random selection of countries.
    Random random = new Random();
    LinkedList<Country> selectedCountries = new LinkedList<Country>();
    for (int i = 0; i < requestedSize; i++)
    {
        int selectedIndex = random.nextInt(allCountries.length);
        selectedCountries.add(allCountries[selectedIndex]);
    }


    // Note: To debug your list, comment this line in
    System.out.println("List of countries: " + selectedCountries);


    // Check if the name of a country is in the list.
    // If the country is found, print the details.
    // Otherwise output not found.
    System.out.println("\nWhat country do you want to search for?");
    String countryToFind = keyboard.nextLine();
    //Country obj = new Country(countryToFind);
    Country foundCountry = selectedCountries.contains(new Country(countryToFind));
    if (foundCountry != null)
    {
        System.out.println("Country " + countryToFind + " found with details:\n" + foundCountry);
    }
    else
        System.out.println("Country " + countryToFind + " not found.");

}

The output code below: Belize is printed on to the screen, I type in Belize and it says not found even though Belize is in the list

How many countries do you want to add to the list?
4
 European Union 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.010455902 0.014641232 0.022017047 0.033736759 0.059970029 0.099394983 0.172494402 0.290883796 0.468609861 0.647271896 0.88803523  1.180245548 1.773778201 2.896911981 4.555055819 7.189007007 11.51481484 19.70441779 33.91179565 53.57287113 64.80565912 70.93170081 77.89306636 85.94063784 95.79155903 105.012288  115.1562612 120.8409684 121.1416294 119.2250553 121.9304985 123.7159497 
 Sint Maarten (Dutch part)  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 
 Belize 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.201592581 0.411172831 0.747480214 1.028369629 1.164387324 1.570531759 2.842663676 7.046515722 15.96872731 20.54645981 23.38066005 28.29761545 35.30450132 42.2961808  41.34020042 54.51721037 53.74564807 62.93070205 70.31965347 53.20712214 
 Uganda 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.008423042 0.018684872 0.022640286 0.131691862 0.239741703 0.522799789 1.130100554 1.516028656 2.892006194 4.195756068 4.578959089 6.761102482 13.65261655 26.92003559 28.55294653 37.74438345 47.50472743 45.00206351 
 List of countries: 
 What country do you want to search for?
 Belize
 Country Belize not found.
2

There are 2 best solutions below

0
On BEST ANSWER

Answering in new response so I can quote code.

back @LALA. This particular problem is not generics, it's how to override the key method, equals(Object) defined in java.lang.Object. To override a method from the base class you have to get the signature spot on. Easy to mess up, somewhere (java 1.4??) java added the method annotation @Override. This tells the compiler (and anyone reading the code ... including you tomorrow) that "This method is intended to override a method from the base class (or interface); if it is not please throw a compile-time-error because I have f-ed up.

Following this guideline, you would have typed:

//overrides the equals method and returns country name if found
@Overrides
public boolean equals(Country obj)
...

The compiler would jump in and save you here, noting that it does NOT override anything. Correct would be:

//overrides the equals method and returns country name if found
@Overrides
public boolean equals(Object obj)
...

I would like to add... you have committed a major-java-developer-sin. You have [attempted to] write equals(), but you have not also overridden hashCode() (again specifying @Override is even more vital here (I personally often forget to capitalize the 'C').) Seriously, never write one of these 2 methods w/o the other.

As an assignment for this answer, read the following carefully:

https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals(java.lang.Object)

https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()

4
On

When you override equals, it has to be equals(Object), not equals(YourClassName). You haven't actually overridden the method; you've made a separate method with the same name, which LinkedList won't call.