0

I created an object Student using Comparable with getters/setters as well as a method that overrides compareTo. In a separate file an arraylist of objects is populated from a text file. Now I need to compare the values in the arraylist to another Student object.

The file was used to create an arraylist as below:

    try {
    private static ArrayList<Student> array = new ArrayList<Student>();
    File file = new File("students.txt");
    Scanner scanner = new Scanner(file);

    while (scanner.hasNextLine()) {                
        String inline = scanner.nextLine();
        String[] split = inline.split(":");
        Student myStudent  = new Student();
        myStudent.setUsername(split[0]);
        myStudent.setPassword(split[1]);

        array.add(myStudent);

    }
    scanner.close();
    }
    catch (FileNotFoundException e)
    {
    System.out.println("ERROR.");
    }

The text file looks like this:

John:password1

Jane:password2

Jack:password3

(One on each line, no blank lines in between.)

And in a separate method a created Student object is compared to the elements in the arraylist:

    Student aStudent = new Student();
    aStudent.setUsername("student");
    aStudent.setPassword("password");
    boolean found = false;
    for (int i = 0; i < array.size(); i++)
    {
    if (array.get(i).compareTo(aStudent) == 0)
    {
      System.out.println(aStudent.equals(array.get(i)));
      found = true;
      break;
    }
    else
    {
      System.out.println("No such records found!");
      found = false;
      break;
    }
    System.out.println(found);
    }

The problem is that the object aStudent is not being compared with the objects in the arraylist. It does not print out anything (a -1, 0, or 1) for the call to compareTo, but it always shows that found is true, even though it should be false when there are no matches for aStudent in the file (which there aren't any matches to the username "student" or the password "password").

All together my code complies and works - it just works incorrectly.

Sorry if this sounds confusing. In short, my question is how can I compare the objects of an arraylist to another object using the Comparable interface and compareTo? A plus is if you can tell me what I'm doing wrong.

Thank you in advance.

EDIT

Here is the overriding of the compareTo method:

    public int compareTo(Student obj){
    int result = 1;
    if ((this.Username.compareToIgnoreCase(object.Username) < 0) || (this.Password.compareTo(object.Password) < 0))
    {
      result = -1;
    }
    else if ((this.Username.compareToIgnoreCase(object.Username) == 0) && (this.Password.compareTo(object.Password) == 0))
    {
      result = 0;
    }

    return result;

    }
  • Are you implementing Comparable interface and overriding compareTo method? Here is useful link: http://stackoverflow.com/questions/18757805/implementing-custom-compareto – Sushant Tambare Oct 08 '14 at 03:22
  • @sushanttambare Thanks for replying and for the link. Yes, I am overriding the compareTo method similarly to the way shown in the link. When I create and compare two Student objects (for example, aStudent.compareTo(bStudent)) it works as expected, so I'm guessing the problem is with the arraylist, but I can't figure out what is causing the problem. – Poetical Scientist Oct 08 '14 at 03:26
  • You seem to be breaking out of the loop prematurely. That is, the `else` statement is breaking the loop, meaning you will only compare the first element in the array and nothing more... – MadProgrammer Oct 08 '14 at 03:28
  • Consider providing a [runnable example](https://stackoverflow.com/help/mcve) which demonstrates your problem. This will result in less confusion and better responses – MadProgrammer Oct 08 '14 at 03:31

2 Answers2

1

More context would be useful, but your for-loop looks wrong...

for (int i = 0; i < array.size(); i++)
{
    if (array.get(i).compareTo(aStudent) == 0)
    {
        System.out.println(aStudent.equals(array.get(i)));
        found = true;
        break; // out of loop
    }
    else
    {
        System.out.println("No such records found!");
        found = false;
        break; // break out loop
    }
    System.out.println(found);
}

The break statement is used to break out of the loop, meaning that you will only ever compare the first element in the list.

The entire else branch isn't required (or at least I don't think it is ;)), for example...

for (int i = 0; i < array.size(); i++)
{
    if (array.get(i).compareTo(aStudent) == 0)
    {
        System.out.println(aStudent.equals(array.get(i)));
        found = true;
        break; // out of loop
    }
}
System.out.println(found);

Updated

Based on you new compareTo code snippet, this...

if ((this.Username.compareToIgnoreCase(object.Username) < 0) || (this.Password.compareTo(object.Password) < 0))
{
  result = -1;
}
else if ((this.Username.compareToIgnoreCase(object.Username) < 0) && (this.Password.compareTo(object.Password) < 0))
{
    result = 0;
}

seems wrong to me...the else if should be more like

else if ((this.Username.compareToIgnoreCase(object.Username) == 0) && (this.Password.compareTo(object.Password) == 0))

if the contract for the Comparable interface is to be met, where 0 is equal...

For example...

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;

public class Test {

    private static ArrayList<Student> array = new ArrayList<Student>();

    public static void main(String[] args) {
        array.add(new Student("John", "password1"));
        array.add(new Student("Jane", "password2"));
        array.add(new Student("Jack", "password3"));

        Student aStudent = new Student("Jack", "password3");
        boolean found = false;
        for (int i = 0; i < array.size(); i++) {
            if (array.get(i).compareTo(aStudent) == 0) {
                System.out.println(aStudent.equals(array.get(i)));
                found = true;
                break;
            }
        }
        System.out.println(found);
    }

    public static class Student implements Comparable<Student> {

        private String name;
        private String password;

        public Student(String name, String password) {
            this.name = name;
            this.password = password;
        }

        public String getName() {
            return name;
        }

        public String getPassword() {
            return password;
        }

        public void setName(String name) {
            this.name = name;
        }

        public void setPassword(String password) {
            this.password = password;
        }

        @Override
        public int compareTo(Student object) {
            int result = 1;
            if ((this.getName().compareToIgnoreCase(object.getName()) < 0) || (this.getPassword().compareTo(object.getPassword()) < 0)) {
                result = -1;
            } else if ((this.getName().compareToIgnoreCase(object.getName()) == 0) && (this.getPassword().compareTo(object.getPassword()) == 0)) {
                result = 0;
            }

            return result;

        }
    }

}

Which will print out...

false
true

Where the objects are not equal but where they are comparable...which is kind of weird...to me ;)

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0

Your problem may lie in the compareTo function that you overrode, you need to include that code otherwise no one can determine why certain values are being returned

EDIT:

Note that when objects are created, they are not necessarily equal solely because their contained values are equal. They are separate instances of the object and treated as such.

You will need to override the equals function as well, not just the compareTo function, in order to get the result that you seek.

Neverwork2123
  • 227
  • 1
  • 5