2016-05-22 1 views
3

Я пытался перебирать коллекцию с помощью forEach, но реализованный вызов remove(Object o) на этой самой коллекции был небезопасным и мог вызвать ConcurrentModificationException. Это то, что я пытаюсь сделать:Сняв элемент из коллекции с помощью Java 8

public void removeMatchup(Set<Player> players) { 
     predefinedMatchups.stream().filter(m -> m.getPlayers().equals(players)).forEach(m -> predefinedMatchups.remove(m)); 
} 

Так у меня было изменено на следующее:

public void removeMatchup(Set<Player> players) { 
    Iterator<Matchup> iterator = predefinedMatchups.iterator(); 
    while (iterator.hasNext()) 
     if (iterator.next().getPlayers().equals(players)) 
      iterator.remove(); 
} 

Мне очень нравится, как лаконичный потоки, поэтому я переработав весь мой проект, чтобы включить Java 8 новых функций.

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

+0

Что вы имеете в виду под «безопасным Вы не хотите получить? исключение ConcurrentModificationException, в то время как вы фактически используете только один поток для удаления, или вы имели в виду потокобезопасность? – Les

ответ

10

Поскольку Set является Collection мы можем использовать removeIf(Predicate<? super E> filter) метод (например, по умолчанию один внутренне использует Iterator и его метод remove так же, как в вашем втором примере).

409 defaultboolean removeIf(Predicate <? super E> filter) {
410 Objects. requireNonNull (filter);
411 boolean removed = false;
412 finalIterator <E> each = iterator();
413 while (each. hasNext()) {
414 if (filter. test (each. next())) {
415 each. remove();
416 removed = true;
417 }
418 }
419 return removed;
420 }

Так что ваш код может выглядеть следующим образом:

public void removeMatchup(Set<Player> players) { 
    predefinedMatchups.removeIf(m -> m.getPlayers().equals(players)); 
} 
+0

Если бы я хотел подключить триггер, если элемент (или элементы) действительно удален, как я могу это сделать? В моем случае, если элемент удален из коллекции, мне нужно будет обновить другие коллекции. Можно ли это сделать с помощью Java 8 или я должен вернуться к своему первоначальному решению? – dabadaba

+1

@dabadaba Lambda может содержать много выражений, один из которых может быть добавлением объекта, который вы удаляете. Таким образом, вы можете попробовать что-то вроде 'removeIf (m -> {boolean result = m.getPlayers(). Equals (players); if (result) otherCollection.add (m); return result;})'. – Pshemo

+0

Я думаю, что значение каждого результата «result» вернуло то, что фактически заставляет метод 'removeIf' запускать удаление элемента или нет, я ошибаюсь? – dabadaba

1

Попробуйте

removeIf:

public void removeMatchup(Set<Player> players) { 
     predefinedMatchups.removeIf(
      value-> players.conainsAll(value.getPlayers()) 
     ); 
} 
Смежные вопросы