2

私の問題は非常に基本的なものですが、それを正しく解決する方法がわかりません。エンティティの名前に基づいたコンパレータを使用する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()メソッドがありますか、それとも私はこれについてすべて間違っていますか?

4

2 に答える 2

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

しかし、このアプローチは非常に醜いです。あなたはそれを避けたほうがいいです。

于 2012-01-25T18:14:53.073 に答える
2

検索が機能しない理由を見つけるための+1。キー付きコレクションでキーを変更可能にすることは、ほとんどの場合間違っています。

方法はありませんset.relayout。あったとしても、あなたはclient code正しいことをする必要があり、それは非常にエラーが発生しやすいです。

したがって、要素を削除して再度追加する必要があります。これも同様にエラーが発生しやすくなります。1つの代替方法は、MyEntity監視可能にextend TreeSetし、要素を削除および追加することによって応答する変更が通知されるようにすることです。

ただし、並行性の懸念はまだあるかもしれませんが、それを解決する1つの方法はMyEntity、コンテナにとを通知beforeChangeすることです。afterChange

于 2012-01-25T18:16:31.890 に答える