Reputation: 1577
As you probably know already, when you put something into a HashMap, the order in which things are stored is random. I want to order my HashMap using Comparable, but I can't get it to work properly.
This so I have a map:
Map<MyKeyObject, List<MyValueObject>> myObjectMap = new HashMap<>();
The key of this map is a construction of multiple an id and a name (MyKeyObject), and I want to sort the map on the keys based on the id first, and if the id is identical then name.
Here is what I've tried:
public class MyKeyObject implements Comparable<MyKeyObject> {
private Long id;
private String name;
public MyKeyObject(Long id, String name) {
this.id = id;
this.name = name;
}
public boolean equals(Long id, String name) {
return this.id.equals(id) && this.name.equals(name)
}
@Override
public int compareTo(MyKeyObject myKeyObject) {
if (this.id myKeyObject.getId() != 0) {
return (this.Id - myKeyObject.getId() == 1) ? 1 : -1;
} else {
return (this.name().compareTo(myKeyObject.name()) == 1) ? 1 : -1;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyKeyObject that = (MyKeyObject) o;
return id.equals(that.id) &&
name == that.name;
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}
public class MyKeyObject implements Comparable<MyKeyObject> {
Map<MyKeyObject, List<MyValueObject>> myObjectMap = new HashMap<>();
//Here I have a lot of code that populates the HashMap
myObjectMap.entrySet().stream().sorted(Map.Entry.comparingByKey());
}
To be honest I don't even think the compareTo method is hit, what am I doing wrong here?
Update: I know that there are types such as TreeMap, but it doesn't work for me. I've just given a very simple example here, my real code is much mode complex. Is it possible to make this work with Comparable like I've tried here?
Upvotes: 0
Views: 103
Reputation: 3592
I think what you are looking for is TreeMap instead of HashMap.
Here you have a simplified example of your use case.
import java.util.Comparator;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
public class TreeMapExample {
public static void main(String[] args) {
Map<MyKeyObject, Object> myTreeMap = new TreeMap<>();
myTreeMap.put(new MyKeyObject(5L, "Jay"), null);
myTreeMap.put(new MyKeyObject(5L, "Bob"), null);
myTreeMap.put(new MyKeyObject(1L, "Alison"), null);
myTreeMap.put(new MyKeyObject(3L, "Frey"), null);
myTreeMap.entrySet()
.forEach(myKeyObjectObjectEntry ->
System.out.println(String.format(
"Id= %s, Name=%s",
myKeyObjectObjectEntry.getKey().id,
myKeyObjectObjectEntry.getKey().name )));
}
public static class MyKeyObject implements Comparable<MyKeyObject> {
private Long id;
private String name;
public MyKeyObject(Long id, String name) {
this.id = id;
this.name = name;
}
@Override
public int compareTo(MyKeyObject myKeyObject) {
return Comparator.comparing((MyKeyObject keyObject)->keyObject.id)
.thenComparing(keyObject->keyObject.name)
.compare(this, myKeyObject);
}
}
}
The output is:
Id=1, Name=Alison
Id=3, Name=Frey
Id=5, Name=Bob
Id=5, Name=Jay
You can make MyKeyObject
Comparable or provider a Comparator to the TreeMap.
Upvotes: 1