Как перебрать SortedSet для изменения элементов внутри

Допустим, у меня есть список. Нет проблем изменить элемент списка в цикле for:

for (int i = 0; i < list.size(); i++) { list.get(i).setId(i); }

Но у меня есть SortedSet вместо списка. Как я могу сделать то же самое с этим? Спасибо

6 ответов

Решение

Прежде всего, Set предполагает, что его элементы являются неизменяемыми (на самом деле, изменяемые элементы разрешены, но они должны придерживаться очень конкретного контракта, что, я сомневаюсь, ваш класс делает).

Это означает, что, как правило, вы не можете изменить заданный элемент на месте, как вы делаете со списком.

Две основные операции, которые Set Опоры - это добавление и удаление элементов. Модификация может рассматриваться как удаление старого элемента с последующим добавлением нового:

  1. Вы можете позаботиться об удалении во время итерации, используя Iterator.remove();
  2. Вы можете накопить дополнения в отдельном контейнере и вызвать Set.addAll() в конце.

Вы не можете изменить ключ набора, потому что это вызывает изменение набора / переупорядочение набора. Таким образом, поведение итерации будет продолжаться неопределенным образом.

Вы можете удалить элементы, используя iterator.remove(). Но вы не можете добавлять элементы, обычно лучшее решение - это накапливать их в новой коллекции и добавлять все после итерации.

Set mySet = ...;
ArrayList newElems = new ArrayList();

for(final Iterator it = mySet.iterator(); it.hasNext(); )
{
  Object elem = it.next();
  if(...)
   newElems.add(...);
  else if(...)
   it.remove();
  ...
}
mySet.addAll(newElems);

Начиная с Java 1.6, вы можете использовать NavigableSet,

Вы должны использовать Iterator или, что еще лучше, расширенный синтаксис цикла for (который зависит от класса, реализующего Iterable интерфейс), независимо от Collectionвы используете Это абстрагирует механизм, используемый для обхода коллекции, и позволяет заменить новую реализацию, не затрагивая процедуру итерации.

Например:

Set<Foo> set = ...

// Enhanced for-loop syntax
for (Foo foo : set) {
 // ...
} 

// Iterator approach
Iterator it = set.iterator();
while (it.hasNext()) {
  Foo foo = it.next();
}

РЕДАКТИРОВАТЬ

Кан делает хорошие замечания относительно изменения ключа элемента. Предполагая, что ваш класс equals() а также hashCode() методы основаны исключительно на атрибуте "id" (который вы меняете), самый безопасный способ - явно удалить их из Set как вы итерируете и добавляете их в "вывод" Set; например

SortedSet<Foo> input = ...
SortedSet<Foo> output = new TreeSet<Foo>();

Iterator<Foo> it = input.iterator();
while (it.hasNext()) {
  Foo foo = it.next();
  it.remove(); // Remove from input set before updating ID.
  foo.setId(1);
  output.add(foo); // Add to output set.
}

Тебе этого не сделать. Но вы можете попробовать, может быть, вам удастся, может быть, вы получите ConcurrentModificationException, Очень важно помнить, что изменение элементов во время итерации может привести к неожиданным результатам. Вместо этого вы должны собрать эти элементы в некоторой коллекции. И после итерации измените их один за другим.

Это будет работать только если id не используется для равных, или компаратор, который вы использовали для отсортированного набора:

int counter = 0;
for(ElementFoo e : set) {
  e.setId(counter);
  couter++;
}
Другие вопросы по тегам