2
import java.util.*;

public class Sort {

    static class ValueComparator implements Comparator<String> {

        Map<String, Integer> base;

        ValueComparator(Map<String, Integer> base) {
            this.base = base;
        }

        @Override
        public int compare(String a, String b) {
            if (base.get(a) >= base.get(b)) {
                return 1;
            } else {
                return -1;
            }
        }
    }

    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        ValueComparator vc = new ValueComparator(map);
        TreeMap<String, Integer> sorted = new TreeMap<String, Integer>(vc);
        map.put("A", 1);
        map.put("B", 2);
        sorted.putAll(map);
        for (String key : sorted.keySet()) {
            System.out.println(key + " : " + sorted.get(key)); // why null values here?
        }
        System.out.println(sorted.values()); // But we do have non-null values here!
    }
}

Output:

A : null
B : null
[1, 2]
BUILD SUCCESSFUL (total time: 0 seconds)

I wonder why we get null values at the first commented line while we do have non-null values as demonstrated by the second commented line.

Edit: @null's version seems not working. I've changed my code as follows:

        public int compare(String a, String b) {
            if (a.equals(b)) return 0;
            if (base.get(a) >= base.get(b)) {
                return 1;
            } else return -1;
        }

It seems to work but I'm not sure.

3 Answers 3

11

My guess is that your ValueComparator.compare() method never returns 0, indicating equality, causing the Map.get() method to not find matches.

Sign up to request clarification or add additional context in comments.

Comments

2

Change your compare to in this way

public int compare(String a, String b) {
        if (base.get(a) > base.get(b)) {
            return 1;
        }else if(base.get(a) ==  base.get(b)){
            return 0;
        }
        return -1;  
    }

4 Comments

Hmm.. Rather I would just have - return base.get(a) - base.get(b);.
Although it seems like an easy out, using the a-b idiom in comparator functions has existed all the way since the days of things like qsort() (and likely even longer) but it carries with it an important shortcoming: If overflow occurs, the result will be incorrect; for example, consider what happens if base.get(a) returns Integer.MIN_VALUE and base.get(b) is positive.
Wait, your code has a key merging problem. Unless you're aware, try it.
You could just do return base.get(a).compareTo(base.get(b)); and let the Integer class handle it.
2

Even with your Comparator which is definitely broken the program will work if you change it as

for (Map.Entry e : sorted.entrySet()) {
    System.out.println(e.getKey() + " : " + e.getValue());
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.