Reputation: 2927
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
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
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
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
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