问题
I'm trying to instantiate a TreeMap
using a Comparator
which should be able to access the said TreeMap
, i.e. the one it will be used for (I guess that "will" must precisly be the problem...):
final Map<String, Integer> map = new TreeMap<String, Integer>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
Integer i = map.get(o1);
// Error: "the local variable map may not have been initialized"
return ...;
}
});
I can get why this error occurs, since when instantiating the Comparator<String>
, the map
variable isn't initialized yet, but is there any workaround solution?
A solution would have been a setComparator
method in the TreeMap implementation, but its comparator
field has been declared as final:
final Map<String, Integer> map = new TreeMap<String, Integer>();
Comparator<String> comparator = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
Integer i = map.get(o1);
return ...;
}
};
// map.setComparator(comparator);
回答1:
Can't you implement Comparator on your class and pass this
to the TreeMap constructor, example:
class MyClass implements Comparator<MyClass> {
private String property;
@Override // java.util.Comparator.compare
public int compare(MyClass o1,
MyClass o2) {
return o1.getProperty().compare(o2.getProperty());
}
@Override // java.util.Comparator.equals
public boolean equals(Object o) {
return this.getProperty().equals(o.getProperty());
}
public String getProperty() {
return this.property;
}
public void setProperty(String myPropertyValue) {
property = myPropertyValue;
}
TreeMap <String, MyClass> myMap = null;
public MyClass() {
myMap = new TreeMap<String, MyClass>(this);
}
If you need further assistance, do leave a comment with more information as to your specific case.
回答2:
Two months later, after having relooked into the answer @hd1 gave me (which doesn't work as is actually), here is a possible solution:
public class SortedByValueMap<K, V extends Comparable<V>> implements Comparator<K> {
private final Map<K, V> map = new TreeMap<K, V>();
private class CustomTreeMap<KK extends K, VV extends V> extends TreeMap<KK, VV> {
private static final long serialVersionUID = 9196929305071517886L;
private CustomTreeMap(Comparator<KK> c) {
super(c);
}
@Override
public VV put(KK key, VV value) {
map.put(key, value);
return super.put(key, value);
};
@Override
public VV remove(Object key) {
map.remove(key);
return super.remove(key);
}
}
@Override
public int compare(K o1, K o2) {
return map.get(o1).compareTo(map.get(o2));
}
public Map<K, V> getMap() {
return new CustomTreeMap<K, V>(this);
}
}
Then:
Map<String, Integer> map = new SortedByValueMap<String, Integer>().getMap();
map.put("r", 2);
map.put("b", 0);
map.put("a", 1);
System.out.println(map); // prints {b=0, a=1, r=2}
But anyway, it has to be considered as a technical challenge solution rather than a real efficient tool though (since two identical parallel maps are created), so use it sparingly... ;)
来源:https://stackoverflow.com/questions/15807453/instantiating-a-treemap-using-a-comparator-which-should-be-able-to-access-the-sa