Search code examples
javasortingdictionarycomparatorcomparable

Is it possible to force Map be sorted in one way, but get values in another way?


I need to have a Sorted Map where all elements are sorted by some key, but I need to be able to get elements by another key.

I assumed that I can solve this task by creating a custom key:

public class MyKey implements Comparable<MyKey>{
    private long id;
    private double price;

    public MyKey(long orderId, double price) {
        this.id = id;
        this.price = price;
    }

    @Override
    public int hashCode(){
        return  Objects.hash(id);
    }

    @Override
    public boolean equals(Object o){
        if(!(o instanceof MyKey)) return false;
        return id == ((MyKey) o).id;
    }

    @Override
    public int compareTo(MyKey o) {
        if(price > o.price) return 1;
        if(price < o.price) return -1;
        return 0;
    }
}

Here is I need to be able to get elements by key, but I need to force Map be sorted by price.

I tried to use:

Map<MyKey, Integer> myTestMap = new ConcurrentSkipListMap<>();
myTestMap.put(new MyKey(1, 200.0), 1);
myTestMap.put(new MyKey(2, 100.0), 2);
myTestMap.put(new MyKey(3, 300.0), 3);
myTestMap.put(new MyKey(6, 500.0), 6);
myTestMap.put(new MyKey(5, 400.0), 5);
myTestMap.put(new MyKey(4, 600.0), 4);

In this case Map is successfully sorted by price, but I can't get the element by using:

System.out.println(myTestMap.get(new MyKey(2, 0)));

I have to set price also to be able to get the element:

System.out.println(myTestMap.get(new MyKey(2, 100.0)));

Are there any workaround in this case?


Solution

  • No real solution to your answer, but an explanation why it is not working: If your dig into ConcurrentSkipListMap you'll see that getting an object checks an internal Index-structure and uses the compareTo method of your Comparable. It is not just using the hashCode method that takes only id into account (for which it would seem plausible to give just your id into the adhoc created MyKey instance). I'd too suggest using a different approach.