TreeSet компаратор на основе изменяемого атрибута - PullRequest
2 голосов
/ 25 января 2012

Моя проблема очень простая, но я понятия не имею, как ее правильно решить. У меня есть 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 ]

2 голосов
/ 25 января 2012

+ 1, чтобы узнать, почему ваш поиск не работает.Почти всегда неправильно разрешать изменение ключа в коллекции ключей.

Нет способа set.relayout.Даже если бы это было так, вам нужно было бы на client code сделать правильные вещи, и это очень подвержено ошибкам.

Таким образом, вам нужно удалить элемент и добавить его обратно, что также в равной степени подвержено ошибкам.Одна альтернатива - сделать MyEntity наблюдаемым и extend TreeSet так, чтобы он получал уведомления об изменениях, на которые он реагирует, удаляя и добавляя элемент.

Тем не менее могут возникнуть проблемы с параллелизмом, но один из способов решить эту проблему - MyEntity уведомить контейнер с помощью beforeChange и afterChange

2 голосов
/ 25 января 2012

Если у вас есть ссылка на 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);
  }
}

Но такой подход очень уродлив. Тебе лучше избегать этого.

...