I have a HashMap<Object, Student>
where the Object is the ID of the Student, and the Student is an object from Student.
How can I resort the HashMap by the Students name, student->getName()
?
I have a HashMap<Object, Student>
where the Object is the ID of the Student, and the Student is an object from Student.
How can I resort the HashMap by the Students name, student->getName()
?
You might not be able to sort a HashMap, but you can certainly do something that provides the same effect. I was able to sort my HashMap <String, Integer> by descending value of the Integer by using the excellent code posted at the Javarevisited blog. The same principle would apply to a HashMap <String, String> object:
/*
* Java method to sort Map in Java by value e.g. HashMap or Hashtable
* throw NullPointerException if Map contains null values
* It also sort values even if they are duplicates
*/
public static <K extends Comparable,V extends Comparable> Map<K,V> sortByValues(Map<K,V> map){
List<Map.Entry<K,V>> entries = new LinkedList<Map.Entry<K,V>>(map.entrySet());
Collections.sort(entries, new Comparator<Map.Entry<K,V>>() {
@Override
public int compare(Entry<K, V> o1, Entry<K, V> o2) {
return o1.getValue().compareTo(o2.getValue());
// to compare alphabetically case insensitive return this instead
// o1.getValue().toString().compareToIgnoreCase(o2.getValue().toString());
}
});
//LinkedHashMap will keep the keys in the order they are inserted
//which is currently sorted on natural ordering
Map<K,V> sortedMap = new LinkedHashMap<K,V>();
for(Map.Entry<K,V> entry: entries){
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
}
To call this method, I use:
Map<String, Integer> sorted = sortByValues(myOriginalHashMapObject);
Maps cannot be ordered by values. You can do this, though:
Collection<Student> students = map.values();
Collection.sort(new ArrayList<Student>(students)), new Comparator<Student>() {
public int compare(Student s1, Student s2) {
return s1.getName().compareTo(s2.getName());
}
});
Assuming, of course, that you need to iterate over the values. (Why else would you want it ordered like that?)
Good luck.
I would definitely use a New Class that will store the key and the Object.
Then you can put every element of the Map into an ArrayList in the form of this class, and finally use a comparator to sort the ArrayList, afterwards you simply build a new Map. Code will be something like this:
Map<Object, Student> valueMap = new LinkedHashMap<String, String>();
List<Student> pairValueList = new ArrayList<PairValue>();
PairValue p;
for (Map.Entry<Object, Student> entry : map.entrySet()) {
Object key = entry.getKey();
Student value = entry.getValue();
p = new PairValue(key, value);
pairValueList.add(p);
}
Collections.sort(pairValueList, new Comparator<PairValue>() {
@Override
public int compare(PairValue c1, PairValue c2) {
return c1.getLabel().compareTo(c2.getLabel());
}
});
for (PairValue pv : pairValueList) {
valueMap.put(pv.getValue(), pv.getStudent());
}
The PairValue class
class PairValue {
private Object value;
private Student student;
public PairValue(Object value, String student) {
this.value = value;
this.student= student;
}
public String getValue() {
return value;
}
public String getStudent() {
return student;
}
}
Thats the way I solved some similar problem I had in the past. Please Note that the returned map implementation needs to be a LinkedHashMap.
HashMaps cannot be sorted by their values. A Map is designed for constant time lookups based on the key, so ordering by values should not be necessary. If you need to sort by name, I suggest using a SortedSet
and creating a comparator that sorts by the names.
class StudentComparator implements Comparator<Student> {
int compare(Student s1, Student s2) {
return s1.getName().compareTo(s2.getName());
}
}
If you need both a constant time lookup and a sorted-by-value set, then you may need to maintain a map and a set.