Локальная переменная i, определенная во включающей области видимости, должна быть окончательной или фактически конечной - PullRequest
4 голосов
/ 13 июня 2019

Я хочу реализовать эту конечную точку с помощью внутреннего поиска:

@PostMapping("terminals_risk_filter/change_order/{terminalId}")
    public ResponseEntity<?> updateFiltersPositions(@PathVariable Integer terminalId,
            @RequestBody List<ChangeOrderRiskFiltersDTO> newFiltersPositionsList) {

        List<RiskFilters> filterList = riskFilterService.findRiskFiltersByTerminalId(terminalId);

        for (int i = 0; i < newFiltersPositionsList.size(); i++) {
//          RiskFilters filter = filterList.findById(newFiltersPositionsList.get(i).getId());

            Optional<RiskFilters> filter_payload = filterList.stream().filter(f -> newFiltersPositionsList.get(i).getId() == f.getId()).findAny();
            RiskFilters filter = filter_payload.get();      

            filter.setPosition(newFiltersPositionsList.get(i).getPosition());
            riskFilterService.save(filter);
        }
        return ok().build();
    }

Но я получаю сообщение об ошибке Local variable i defined in an enclosing scope must be final or effectively final Можете ли вы дать мне несколько советов, как я могу решить эту проблему, пожалуйста? Например, можно ли пропустить цикл for и использовать, возможно, поток в поток?

Ответы [ 3 ]

5 голосов
/ 13 июня 2019

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

Почему это происходит? Вы можете прочитать об этом здесь: Lambdas: локальные переменные должны быть окончательными, переменные экземпляра не

Минимальные изменения для решения вашей проблемы: не используйте саму переменную i. Создайте его копию и сделайте final.

final int iCopy = i;
Optional<RiskFilters> filter_payload = filterList.stream().filter(f -> newFiltersPositionsList.get(iCopy).getId() == f.getId()).findAny();

Например, можно ли пропустить цикл for и использовать, возможно, stream в stream?

Вы можете попробовать:

// replace the for-loop

// or just.... `newFiltersPositionsList.forEach(/* ... */)`
newFiltersPositionsList.stream().forEach(filterPosition -> {
    Optional<RiskFilters> filter_payload = filterList.stream()
            .filter(f -> filterPosition.getId() == f.getId())
            .findAny();
    RiskFilters filter = filter_payload.get();

    filter.setPosition(filterPosition.getPosition());
    riskFilterService.save(filter);
});

Кроме того, вы можете использовать для каждого вместо для цикла :

for (ChangeOrderRiskFiltersDTO filterPosition : newFiltersPositionsList) {
    Optional<RiskFilters> filter_payload = filterList.stream()
           .filter(f -> filterPosition.getId() == f.getId())
           .findAny();
    RiskFilters filter = filter_payload.get();
    filter.setPosition(filterPosition.getPosition());
    riskFilterService.save(filter);
}
2 голосов
/ 13 июня 2019

Если вы хотите избежать простого решения о добавлении окончательной копии i, вы можете извлечь фактическую «окончательную» информацию:

final int id = newFiltersPositionsList.get(i).getId()

И ваша лямбда может стать:

f -> id == f.getId()
2 голосов
/ 13 июня 2019

Вы можете сделать это, как показано ниже.

final ChangeOrderRiskFiltersDTO dto = newFiltersPositionsList.get(i);
Optional<RiskFilters> filter_payload = filterList.stream().filter(f -> dto.getId() == f.getId()).findAny();
if(filter_payload.isPresent()){
  RiskFilters filter = filter_payload.get();
  //More operations
}
...