Установить свойство каждого объекта в списке с помощью forEach (ошибка: локальные переменные, на которые ссылаются из лямбда-выражения, должны быть окончательными или фактически окончательными)

#lambda #java-8 #java-stream

#лямбда #java-8 #java-stream

Вопрос:

У меня есть список совпадений. Совпадение имеет свойство matchIndex . Теперь я хочу установить свойство каждого совпадения в списке следующим образом

 index = 0 // some predefined value

List<Match> matchList = createMatches(membersList, teamsPerGroup,totalGroups);
    matchList.forEach((match) -> {
    match.setMatchIndex(index  );
});
  

Я хочу установить matchIndex каждого совпадения в списке путем увеличения порядка после индекса локальной переменной.

Комментарии:

1. final int index = 0;

2. Я думаю, что окончательное значение изменить нельзя

Ответ №1:

Вы не можете использовать это, потому что переменные в лямбда-выражении должны быть окончательными или фактически окончательными. вы можете следовать этому коду:

 IntStream.range(0, matchList .size())
            .mapToObj(index -> {
                Match match= list.get(index);
                match.setMatchIndex(index);
                return match;
            })
            .collect(Collectors.toList());
  

или используйте AtomicInteger

 AtomicInteger index= new AtomicInteger(1);
matchList.forEach(match-> match.setMatchIndex(index.getAndAdd(1)));
  

Обновить:

Как прокомментировал @Holger, правильное решение

 IntStream.range(0, matchList.size()) 
         .forEach(index -> matchList.get(index) .setMatchIndex(index));
  

и если вы хотите использовать какое-то предопределенное значение, это правильное решение:

  IntStream.range(0, matchList.size()) 
          .forEach(index -> matchList.get(index) .setMatchIndex(index   offset));
  

Комментарии:

1. Что, если я хочу начать индекс с некоторого предопределенного значения?

2. перейдите ко второму подходу.

3. Правильное решение находится между ними: IntStream.range(0, matchList.size()) .forEach(index -> matchList.get(index) .setMatchIndex(index)); И, кстати, почему вы инициализируете AtomicInteger с помощью одного, противоречащего любому другому примеру?

4. @Holger, спасибо за ваш отзыв. OP прокомментировал, что, если я хочу начать индекс с некоторого предопределенного значения? поэтому я подумал, что для этого был второй способ.

5. Я вижу. Поэтому вы должны прямо в ответе дать понять, что это касается дополнительного момента (поскольку читателям не нужно читать комментарии, чтобы понять ответ). Конечно, это будет работать и с каноническим решением: IntStream.range(0, matchList.size()) .forEach(index -> matchList.get(index) .setMatchIndex(index offset));

Ответ №2:

На самом деле, есть ленивый способ сделать это, но это не способ Java 8. Тем не менее, я публикую этот ответ 🙂

 int index = 0; // starting index

for (Match match: matchList) {
    match.setMatchIndex(matchIndex  );
}
  

Надеюсь, это поможет.