2015-02-24 74 views
0

我看到設置比較器的唯一方法是通過TreeMap構造函數。例如:在運行時更改樹形圖比較器

TreeMap myMap = new TreeMap(myComparator); 

但是,我想確定在運行時使用什麼類型的比較器。我可以創建多個TreeMaps或一個新的實例,但是我發現它留下了更大的內存空間。

有沒有辦法做到這一點?或者我的設計存在缺陷?

回答

2

我建議你推遲創建TreeMap,直到你知道哪個Comparator將是合適的。如果這是不可能的(例如,因爲您需要使用對TreeMap的引用來初始化其他對象),請考慮將TreeMap隱藏在將懶惰地初始化它的方法或類後面,或者使用Factory模式。如果這也不可行,請使用您自己的Comparator實施初始化TreeMap,然後在那裏作出決定(在您開始向TreeMap添加項目之前,不會調用compareTo())。

至於爲什麼TreeMap(或採取Comparator其他大多數集合)將不允許你改變Comparator,看到@Evgeniy Dorofeev的答案。

+0

或者,使用更改後的比較器創建一個新的TreeMap,並從現有的TreeMap中創建一個新的TreeMap。 – user949300 2015-02-24 06:35:49

+0

@ user949300:這也可以,但是如果'TreeMap'是從很多地方引用的(這將全部需要更新),它可能會變得混亂。 – 2015-02-24 06:39:56

1

TreeMap不允許更改比較器,因爲內部樹結構依賴於比較器,並且更改它會使內部樹無效。

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; 

.... 
0

你可以做這樣的事情:

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。你唯一要消除的是內存分配。