views:

67

answers:

4

I have tried almost everything and I can't seem to get my lists to order themselves. Here's some code:

private List<Person> names = new ArrayList<Person>(); 
private Map<Integer, Person> peopleMap = new TreeMap <Integer, Person>();
for(int i = 0; i<20; i++)
        {
        Person personOne = new Person();
        peopleMap.put(personOne.id,personOne);
        names.add(personOne);
        }
        Collections.sort(names);
        run();
    }



My Person class:
public class Person implements Comparable {
    public String name;
    public int id;
    public Date birthdate;
    static int idRecord = 0;

The values are filled with randoms. My date has a date format.

I also have a toString method inside my person class, but for some reason when I try to print my maps it gives me the hashcode (this is the hashcode right?) Person@a62fc3. Here is my toString inside the person clasS:

             public String toString()
    {

        char tab = '\t';
        return ("ID Number: "+id+tab+" Name: "+tab+name+tab+" Birthdate: "+(birthdate.toString()));

    }

I should add that I am not able to call my toString method inside my person class. Because it is printing Person@a62fc3.

public void sortByID()
{
    char tab = '\t';

    for (int i = 1; i<20; i++)
    System.out.println((peopleMap.get(i)).toString());
    //System.out.println("ID Number: "+(peopleMap.get(i).id)+tab+" Name: "+tab+peopleMap.get(i).name+tab+" Birthdate: "+peopleMap.get(i).birthdate);
    run();

}

The commented code will work but the code calling the toString does not print what it should

Compare to method inside of my Person class:

public int compareTo(Object obj) {
 Person o = (Person) obj; 
if (this.id == o.id) { return 0; }
 if (this.id > o.id) { return 1; } 
if (this.id < o.id) { return -1; } 
return 0;

I can provide more code if it's needed.

Compare by name method and it's output. Should I make an arrayList to store my values in and then sort it in that?

    public void sortByName()
    {
//      char tab = '\t';

        for(int j = 1; j<20; j++)
        {
//          System.out.println("ID Number: "+(names.get(j).id)+tab+" Name: "+tab+peopleMap.get(j).name+tab+" Birthdate: "+peopleMap.get(i).birthdate);
            //Person p = names.get(j);
            System.out.println(names.get(j).toString());
        }
    }

Output: Person@10b30a7 Person@1a758cb Person@1b67f74 Person@69b332 Person@173a10f Person@530daa Person@a62fc3 Person@89ae9e Person@1270b73 Person@60aeb0 Person@16caf43 Person@66848c Person@8813f2 Person@1d58aae Person@83cc67 Person@e09713 Person@de6f34 Person@156ee8e Person@47b480

Thanks

A: 

Well, I can't pinpoint the exact problem, I have a few suggestions.

Maps aren't sorted.

In general, an Map is not sorted, so you will not be able to sort the keys of the map. If you want to sort the Map use the SortedMap interface.

Use Generics when possible

The Comparable interface is generic. You should probably be implementing Comparable<Person>

Then your compareTo() method should look like this:

public int compareTo(Person p) {
    if (this.id > p.id) return 1;
    else if (this.id < p.id) return -1;
    else return 0;
}

The difference between Comparator<Person> and Comparable<Person>

You need to take a look at the Comparator interface as well as the Comparable interface.
Your Person should implement comparable in that way that you usually want a person to be sorted. Then you should write some implementations of Comparator.

public classPersonNameComparator implements Comparator<Person> {

    public int compare(Person p1, Person p2) {
        return p1.name.compareTo(p2.name);
    }
}

The importance of using the @Override annotation

It is important to always use the @Override annotation whenever you are trying to override a method of a super class or implement an interface method. The following are a few links regarding why this is a good idea:

jjnguy
He's using `TreeMap` which is a `SortedMap`. Limiting the variable to the `Map` interface shouldn't affect the order at all.
Gray
Thanks Justin,your compare to method is nearly identical to mine except for the params. Currently the method for sorting by ID works fine. How can I sort a sorted map? is it sorted by default when you add the values or do you perform a method call on it? It was suggested to me to use comparators, but I have no idea how to use them. I have 2 classes that extend comparator with compareTo methods. When I try to change the params from Obj to Person so I can reference variables within the Person class, it tells me I am not overriding the method and that I need to in order to implement comparator
Cody
Thank you! This solved my problem. Thanks to everyone for all the help.
Cody
@Cody Glad I could help. You should consider [marking this as the accepted answer](http://meta.stackoverflow.com/questions/5234/how-does-accepting-an-answer-work) so that people with the same problem as you will know how you solved your issue.
jjnguy
all of these responses were extremely helpful, I almost wish I could print them out for notes..
Cody
@cody There is an app for that: [Stack Printer](http://stackprinter.appspot.com/)
jjnguy
A: 

One issue that I see is that TreeMap sorts by key not by value. Your compareTo will not be used in the sorting of the tree since it is the value in the map. Since the key in the map is the id the the items in the tree should be sorted by the id of the person.

How do you know that the map isn't sorted? Can you show us some output that shows that it is not? Are you by any chance changing the ID of the Person after it gets put into the map?

Oh, and what is names compared to personMap? Also, are the ids really contiguous starting from 1? What does this code spit out:

for (Person person : peopleMap.values()) {
    System.out.println(person);
}
Gray
Well I can't be sure if the map is sorted because of what it's printing out. If I could get it to use my toString method I would be able to tell.I will add the output and method for my CompareByName.
Cody
What does the for loop that I posted spit out Cody? Also, if you say `p = new Person()` ... and then spit out `p.toString()` does that work?
Gray
This also makes me wonder if I need a compareTo inside of my person class? Because a treeMap will sort it's values automatically (the id variable happens to be the key).There are 20 members of person class, indexed 1-20, it's their ID.Names is an arrayList that was attempting to fill with the elements from peopleMap and sort it/print it. Couldnt get it to work.
Cody
Your loop printed this Gray:Person@10b30a7Person@1a758cbPerson@1b67f74Person@69b332Person@173a10fPerson@530daaPerson@a62fc3Person@89ae9ePerson@1270b73Person@60aeb0Person@16caf43Person@66848cPerson@8813f2Person@1d58aaePerson@83cc67Person@e09713Person@de6f34Person@156ee8ePerson@47b480Person@19b49e6
Cody
Something is really wrong if you `toString` method does not work. The code you listed in the question looks fine. Are you sure you are using that class? Can you post the entire code to http://pastie.org/ ?
Gray
http://pastie.org/1051003 That is my Main class, it handles the menu and holds the lists.
Cody
http://pastie.org/1051005 That is my person class.
Cody
This works fine for me: http://pastie.org/1051006
Gray
Your code spits out the right toString information for me. Maybe you need to clean your build environment? Maybe you are using an old class file by mistahge? The output is also sorted by id fine. The alternative sorting doesn't work since the map can only be sorted one way.
Gray
System.out.println("ID Number: "+(names.get(j).id)+tab+" Name: "+tab+peopleMap.get(j).name+tab+" Birthdate: "+peopleMap.get(i).birthdate);Person p = names.get(j);This doesn't even work. Wtf?
Cody
Apologies for being new but what do you mean by cleaning one's build environment? I will check to make sure I am using the right classes.
Cody
I can sort lists with ArrayList right? What do you think of copying all of the elements from my Map into the array list and ordering that?
Cody
A: 

did you use the @Override method to make sure that you are actually overriding the toString method? It looks like it is still printing out the default toString() (ie the value of the pointer to the object).

Aviendha
Just added it above my method, I did not have it. Still no luck, it is printing the same.
Cody
A: 

Hello,

see : comparator API.

"The ordering imposed by a Comparator c on a set of elements S is said to be consistent with equals if and only if (compare((Object)e1, (Object)e2)==0) has the same boolean value as e1.equals((Object)e2) for every e1 and e2 in S."

I don't see an equals method in your Person class. The default implementation of equals compares identity. And if you override equals, you must define hashCode two.

And this question : Consistent Equals() results, but inconsistent TreeMap.containsKey() result

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;


public class Person implements Comparable<Person> { 
    public final String name;
    public final int id;
    public final Date birthdate;

    public Person(int id, String name, Date birthdate) {
        this.id = id;
        this.name = name;
        this.birthdate = birthdate;
    }

    public static void main(String[] args) {    
        List<Person> list = new ArrayList<Person>();
        for (int i = 10; i > 0; i--) {
            list.add(new Person(i, "name" + String.valueOf(i), new Date()));
        }
        System.out.println(list);
        Collections.sort(list);
        System.out.println(list);
    }

    @Override
    public boolean equals(Object other) {
        if (!(other instanceof Person)) {
            return false;
        }
        return this.id == ((Person)other).id;
    }

    @Override
    public int hashCode() {
        return 41 * id;
    }

    @Override
    public String toString() {
        return "Person<" + id + ">";
    }

    @Override
    public int compareTo(Person other) {
        if (!(other instanceof Person)) {
            throw new IllegalArgumentException();
        }
        return this.id - ((Person)other).id;
    }
}

Outputs :

[Person<10>, Person<9>, Person<8>, Person<7>, Person<6>, Person<5>, Person<4>, Person<3>, Person<2>, Person<1>]
[Person<1>, Person<2>, Person<3>, Person<4>, Person<5>, Person<6>, Person<7>, Person<8>, Person<9>, Person<10>]
Bruno Thomas