lord12
lord12

Reputation: 2927

Why do I get a list of null values when I print out values from TreeMap?

I am new to Java and am using the TreeMap Code example that was on this site but when I try to iterate through the TreeMap, I get a list of null values but when I print the map directly I can see the key/value pairs. How do I rectify this?

import java.util.*;
public class Testing {

    public static void main(String[] args) {

        HashMap<String,Double> map = new HashMap<String,Double>();
        ValueComparator1 bvc =  new ValueComparator1(map);
        TreeMap<String,Double> sorted_map = new TreeMap<String,Double>(bvc);

        map.put("A",99.5);
        map.put("B",67.4);
        map.put("C",67.4);
        map.put("D",67.3);

        System.out.println("unsorted map: "+map);

        sorted_map.putAll(map);


        System.out.println("results: "+sorted_map);

        for(String key: sorted_map.keySet())
        {
            System.out.println(sorted_map.get(key)); //null values-Why?
        }
    }
}

class ValueComparator1 implements Comparator<String> {

    Map<String, Double> base;
    public ValueComparator1(Map<String, Double> base) {
        this.base = base;
    }

    // Note: this comparator imposes orderings that are inconsistent with equals.    
    public int compare(String a, String b) {
        if (base.get(a) >= base.get(b)) {
            return -1;
        } else {
            return 1;
        } // returning 0 would merge keys
    }
}

Upvotes: 1

Views: 564

Answers (4)

Evgeniy Dorofeev
Evgeniy Dorofeev

Reputation: 136162

Since your comparator never returns 0 TreeMap.get() does not work. Still you can iterate over TreeMap entries like this

    for (Entry<String, Double> e : sorted_map.entrySet()) {
        System.out.println(e);
    }

prints

A=99.5
C=67.4
B=67.4
D=67.3

Upvotes: 1

sakthisundar
sakthisundar

Reputation: 3288

The code of Adam Crume is very important. To explain you more on this, when you call your sorted_map.get(key), it goes to java.util.TreeMap class', getEntryUsingComparator method because you have set the comparator explicitly. This method looks like

final Entry<K,V> getEntryUsingComparator(Object key) {
        K k = (K) key;
        Comparator<? super K> cpr = comparator;
        if (cpr != null) {
            Entry<K,V> p = root;
            while (p != null) {
                int cmp = cpr.compare(k, p.key);
                if (cmp < 0)
                    p = p.left;
                else if (cmp > 0)
                    p = p.right;
                else
                    return p;
            }
        }
        return null;
    }

Since there is comparison for keys in your compare method of your value comparator, the entry will be null and hence value will also be null because map.get is implemented as

 public V get(Object key) {
        Entry<K,V> p = getEntry(key);
        return (p==null ? null : p.value);
    }

Upvotes: 0

Mihai Danila
Mihai Danila

Reputation: 2348

Sorry, but your example is a bit upside down. You're putting keys into a sorted map (tree map) but then using the values as keys in the sense that you compare by the values. It looks like you're looking to handle objects that have a key and a value, so here's something you might want to consider. This would certainly be the OOP way to handle "compound" concepts like the one you're modeling with a map.

class Pair implements Comparable<Pair> {
    String value;
    double key;

    Pair(String value, double key) {
        this.value = value;
        this.key = key;
    }

    public int compareTo(Pair p) {
        return Double.compare(key, p.key);
    }

    public String toString(Pair p) {
        return value + "," + key;
    }
}

static void main(String[] args) {
    Set<Pair> unsortedSet = new HashSet<Pair>();
    unsortedSet.add(new Pair("A", 99.5));
    unsortedSet.add(new Pair("B", 67.4));
    unsortedSet.add(new Pair("C", 67.4));
    unsortedSet.add(new Pair("D", 67.3));

    Set<Pair> sortedSet = new TreeSet<Pair>();
    sortedSet.add(new Pair("A", 99.5));
    sortedSet.add(new Pair("B", 67.4));
    sortedSet.add(new Pair("C", 67.4));
    sortedSet.add(new Pair("D", 67.3));

    System.out.println("Unsorted set: " + unsortedSet);
    System.out.println("Sorted set: " + sortedSet);

    for (Pair pair : sortedSet) {
        System.out.println(pair);
    }
}

Upvotes: 3

Adam Crume
Adam Crume

Reputation: 15844

It doesn't work because your comparator doesn't return 0 when given identical keys, e.g. compare("A", "A"). Change it to

    public int compare(String a, String b) {
        Double va = base.get(a);
        Double vb = base.get(b);
        if(va > vb) {
            return -1;
        } else if(va < vb) {
            return 1;
        } else {
            return a.compareTo(b);
        }
    }

and it'll work.

Upvotes: 6

Related Questions