Как перебрать SortedSet для изменения элементов в - PullRequest
3 голосов
/ 29 ноября 2011

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

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

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

Ответы [ 6 ]

5 голосов
/ 29 ноября 2011

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

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

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

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

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

Вы можете удалить элементы, используя 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);
2 голосов
/ 29 ноября 2011

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

2 голосов
/ 29 ноября 2011

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

2 голосов
/ 29 ноября 2011

Вы должны использовать 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();
}

EDIT

Кан делает хорошие замечания относительно изменения ключа предмета. Предполагая, что методы 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.
}
1 голос
/ 29 ноября 2011

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

int counter = 0;
for(ElementFoo e : set) {
  e.setId(counter);
  couter++;
}
...