Удалить элемент из набора
Я пытаюсь удалить все строки одинаковой длины в наборе. Вот мой код, но у меня проблемы с получением индекса от итератора в расширенном цикле.
public static void removeEvenLength(Set<String> list) {
for (String s : list) {
if (s.length() % 2 == 0) {
list.remove(s);
}
}
}
3 ответа
Set
не имеет понятия индекса элемента. Элементы не имеют порядка в наборе. Кроме того, вы должны использовать Iterator
при итерации, чтобы избежать ConcurrentModificationException
при удалении элемента из коллекции при зацикливании:
for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
String s = iterator.next();
if (s.length() % 2 == 0) {
iterator.remove();
}
}
Обратите внимание на призыв к Iterator.remove()
вместо Set.remove()
,
Java 8 представила Collection.removeIf (), которая позволяет вам делать:
set.removeIf(s -> s.length() % 2 == 0)
Просто подумал, что выложу решение Java 8, которое может кому-то помочь в будущем. Java 8 Streams предлагает множество хороших методов, таких как filter
а также collect
, filter
Метод просто отфильтровывает элементы из потока, которые следует перенести на следующий шаг. collect
Метод объединяет элементы в Collection
какой-то или Map
,
// The data to filter
final Set<String> strings =
new HashSet<>(Arrays.asList("a", "ab", "abc", "abcd"));
// Now, stream it!
final Set<String> odds =
strings.stream()
.filter(s -> s.length() % 2 != 0) // keep the odds
.collect(Collectors.toSet()); // collect to a new set
Это фактически не изменяет исходную коллекцию, но создает новую Set
содержащий String
объекты нечетной длины.
Для получения дополнительной информации о потоках Java 8 обратитесь к этому превосходному учебнику от Oracle или замечательных JavaDocs.
Вам не нужен индекс. Но вам нужно явное Iterator
, Итератор имеет remove()
метод, без параметров, который удаляет текущий элемент из коллекции.
Iterator<String> itr = list.iterator(); // list is a Set<String>!
while (itr.hasNext())
{
String s = itr.next();
if (s.length() % 2 == 0) {
itr.remove();
}
}