How can I order TreeMaps or ArrayLists holding Persons based on their ID, name, or birthdate?
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 <I开发者_StackOverflow中文版nteger, 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
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:
- Overriding the java equals() method quirk
- When do you use Java's @Override annotation and why?
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);
}
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).
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>]
精彩评论