我看到设置比较器的唯一方法是通过TreeMap构造函数。例如:
TreeMap myMap = new TreeMap(myComparator);
但是,我想决定在运行时使用什么类型的比较器。我可以创建多个TreeMaps或一个新的实例,但我发现它留下了更大的内存占用。
有没有办法实现这个目标?或者我的设计缺陷是什么?
答案 0 :(得分:3)
我建议您推迟创建TreeMap
,直到您知道哪个Comparator
是合适的。如果这是不可能的(例如,因为您需要通过引用TreeMap
来初始化其他对象),请考虑将TreeMap
隐藏在将懒惰地初始化它的方法或类后面,或者使用Factory模式
如果这也是不可能的,请使用您自己的TreeMap
实施初始化Comparator
,并在那里做出决定(compareTo()
不会被调用,直到您开始添加项目为止TreeMap
)。如果你走这条路,你必须非常小心在你开始向树中添加项目后不改变比较器的行为!
至于为什么 TreeMap
(或大多数采用Comparator
的其他集合)不允许您更改Comparator
,请参阅@ Evgeniy Dorofeev的回答。
答案 1 :(得分:1)
TreeMap不允许更改Comparator,因为内部树结构依赖于比较器,更改它会使内部树无效。
答案 2 :(得分:1)
你可以这样做:
class MyCompartor<T> implements Comparator<T> {
Comparator<T> changeableComparator;
public void setComparator(Comparator<T> comparator) {
this.changeableComparator = comparator;
}
@Override
public int compare(T o1, T o2) {
return changeableComparator.compare(o1, o2);
}
}
但这会很疯狂。您不能也不能在运行时更改TreeMap
&#39; Comparator
。树不会根据新的Comparator
进行重新组织。
相反,为每个新TreeMap
创建一个新的Comparator
(即如果您知道其他人建议的比较类型,则无法初始化地图。)
或者,继承TreeMap并使用上面的可更改Comparator
添加重组方法,但实际上这与创建新TreeMap
几乎相同(性能明智)。你唯一要消除的是内存分配。
答案 3 :(得分:0)
您可以通过以下方式实施比较器:
//first impl
final Comparator<String> first = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return 0;
}
};
//second impl
final Comparator<String> second = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return 0;
}
};
Comparator<String> inst=first;
//Treemap initialization
TreeMap<String, String> t = new TreeMap<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
//call of the impl
return inst.compare(o1, o2);
}
});
.....
//switch during runtime
inst = second;
....