2012-01-25 43 views
2

我的問題是非常基本的,但我不知道如何正確解決它。我有一個TreeSet,它使用基於實體名稱的比較器。但是,我可以改變這個名字。我如何強制重新排序TreeSet?基於可變屬性的TreeSet比較器

TreeSet<MyEntity> set = new TreeSet<MyEntity>(new BeanComparator("name")); 
// bar < foo < xander 
set.add(foo); 
set.add(bar); 
set.add(xander); 
// resulting tree:  _-foo-_ 
//     bar xander 
xander.setName("apple"); 

set.contains(xander); // -> false, since now neither 'foo' or 'bar' are equal to 'xander' 

是否有一些set.relayout()方法我應該打電話,還是我去談這全錯了?

回答

2

如果在更改元素名稱時有鏈接到TreeSet,只需從該集合中刪除該元素,更改其名稱並插回。

如果你沒有在更新名字的時候,鏈接,然後我會建議把它作爲myEntity所私有字段,並重寫的setName()作爲

public class MyEntity { 
    private final TreeSet<MyEntity> container; 

    ... 

    public void setName(final String name) { 
    container.remove(this); 
    this.name = name; 
    container.add(this); 
    } 
} 

但是,這方法非常難看。你最好避免它。

+0

否,後一種方法是更好地通知容器,首先是容易出錯。 –

2

+1瞭解爲什麼您的搜索不起作用。允許密鑰在密鑰集合中可變的幾乎總是錯誤的。

沒有set.relayout方法。即使有,你也需要在client code上做正確的事情,這是非常容易出錯的。

因此,您需要刪除元素並將其添加回來,這也同樣容易出錯。一種替代方法是使MyEntity可觀察,extend TreeSet,以便通過刪除和添加元素來獲知它所響應的更改。

仍有可能併發的擔憂,雖然,一個方法來解決它是MyEntitybeforeChangeafterChange