0

I have to make sorted map which key is int[] and value is double. It cant be swapped because double will be duplicated. Moreover, map will be sort by value and last x values will be deleted.

I tried to make

Map<int[],Double> map = new TreeMap<>();;
int[] i = {0,1,1,0};  
    map.put(i,8.5);  // ERROR HERE Organisms.java:46
    i = new int[]{0,0,0,0};
    map.put(i,30.0);
    System.out.println("sorted" + sortByValue(map));

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: [I cannot be cast to java.lang.Comparable at java.util.TreeMap.compare(TreeMap.java:1294) at java.util.TreeMap.put(TreeMap.java:538) at com.pszt_organism.Organisms.test(Organisms.java:46) <-- MARKED ERROR

I found method sortByValue(Map<K, V> map) in this topic: java8 example by Carter Page

I suppose that TreeMap has problem with sorting table of int. How to solve that?

EDIT:

private  <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
        return map.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByValue(/*Collections.reverseOrder()*/))
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (e1, e2) -> e1,
                        LinkedHashMap::new
                ));
    }
Xalion
  • 543
  • 7
  • 22

3 Answers3

3

The problem is that Java array types do not implement Comparable.

The solution: implement a Comparator that will compare your int[] keys, and pass an instance as a parameter to the TreeMap constructor.

However, this will only work if the int[] objects are not mutated while they are in use as keys. If you mutate them, then you will "break" the TreeMap and Map operations will behave incorrectly.

You could also wrap the int[] objects in a class that implements Comparable, implement compareTo, equals and hashCode. The same caveat about mutation applies with this approach as well.

Stephen C
  • 632,615
  • 86
  • 730
  • 1,096
1

int[] arrays as poorly suited for use as keys in a Map (see this Q&A for a brief explanation; it talks about array lists, but the same logic applies to arrays as well).

If you are set on using arrays as keys anyway, proceed with caution:

Since int[] is not Comparable, you cannot use it as a key without supplying a piece of logic for comparing arrays.

Here is how you can do it:

Map<int[],Double> map = new TreeMap<>(
    new Comparator<int[]>() {
        @Override public int compare(int[] lhs, int[] rhs) {
            int len = Math.min(lhs.length, rhs.length);
            for (int i = 0 ; i != len ; i++) {
                if (lhs[i] != rhs[i]) {
                    return Integer.compare(lhs[i], rhs[i]);
                }
            }
            // If we're here, common elements match up;
            // hence, the longer of the two arrays wins.
            return Integer.compare(lhs.length, rhs.length)
        }           
    }
);
Sergey Kalinichenko
  • 675,664
  • 71
  • 998
  • 1,399
  • 1
    This, except you should just keep a final static comparator and pass it on. Slightly more permanent memory usage, a lot less allocation. – coladict May 22 '17 at 13:20
0

You don't need to use TreeMap to use that sorting method. Just use a different Map. That sorting method creates a new LinkedHashMap for the result, so the Map which is passed as an argument is just a temporary container.

Radiodef
  • 35,285
  • 14
  • 78
  • 114