在运行时更改树图的比较器

Change comparator of treemap during runtime

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

 TreeMap myMap = new TreeMap(myComparator);

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

有办法实现吗?还是我这边有设计缺陷?

我建议您推迟 TreeMap 的创建,直到您知道哪个 Comparator 是合适的。如果这是不可能的(例如,因为您需要使用对 TreeMap 的引用来初始化其他对象),请考虑将 TreeMap 隐藏在将延迟初始化它的方法或 class 后面,或者使用工厂模式。

如果这也是不可能的,请使用您自己的 Comparator 实现来初始化 TreeMap,并在那里做出决定(compareTo() 在您开始向其中添加项目之前不会被调用TreeMap)。如果你走这条路,你必须非常小心,不要在你开始向树中添加项目后改变比较器的行为!

至于 为什么 TreeMap(或大多数其他采用 Comparator 的集合)不允许您更改 Comparator ,请参阅@Evgeniy Dorofeev 的回答。

TreeMap 不允许更改 Comparator,因为内部树结构依赖于 Comparator,更改它会使内部树无效。

您可以按如下方式实现您的比较器:

//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;

....

你可以这样做:

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);
    }
}

但这太疯狂了。您不能也不得在运行时更改 TreeMapComparator。树不会根据新的 Comparator.

自行重组

相反,为每个新的 Comparator 创建一个新的 TreeMap(也就是说,如果您无法像其他人建议的那样在已知比较类型时初始化映射)。

或者,将 TreeMap 子类化并添加一个具有上述可变 Comparator 的重组方法,但实际上这与创建新的 TreeMap 几乎相同(性能方面)。您唯一要消除的是内存分配。