在运行时更改treemap的比较器

时间:2015-02-24 06:08:51

标签: java comparator treemap

我看到设置比较器的唯一方法是通过TreeMap构造函数。例如:

 TreeMap myMap = new TreeMap(myComparator);

但是,我想决定在运行时使用什么类型的比较器。我可以创建多个TreeMaps或一个新的实例,但我发现它留下了更大的内存占用。

有没有办法实现这个目标?或者我的设计缺陷是什么?

4 个答案:

答案 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;

....