Вы видите аномалию DD, потому что переменная newId
переопределяется в do { } while(true)
l oop, когда условие if оценивается как ложное.
Аномалия DU, однако, является ложноположительным , Думаю. В этом случае newId
всегда используется хотя бы один раз:
- если список элементов пуст, то возвращается
newId
- , если список элементов не пуст , тогда
newId
используется в закрытии nonMatch
Но это то, что PMD не может понять, потому что он не знает семантику noneMatch
. Если вы замените noneMatch
на anyMatch
, это будет настоящая аномалия DU.
Аномалии DD и DU часто трудно исправить, потому что они указывают на проблемы дизайна на более высоком уровне. В этом случае проблема заключается не непосредственно в самой переменной newId
, а в использовании do { } while(true)
, что может привести к бесконечному l oop, потому что вы игнорируете случай, когда вы не можете сгенерировать новый уникальный идентификатор.
Один из способов решить эту проблему - решить эту проблему:
private String generateNewId(List<Item> items) {
return Stream.generate(this::getRandomId)
.limit(100)
.filter(id -> isNew(id, items))
.findAny()
.orElseThrow(() -> new NoSuchElementException("Failed to generate unique id."));
}
private String getRandomId() {
return "4"; // chosen by fair dice roll.
// guaranteed to be random.
}
private boolean isNew(String id, List<Item> items) {
return items.stream().noneMatch(item -> id.equals(item.getId()));
}
Это решение решает проблему бесконечного l oop, пытаясь сгенерировать новый идентификатор не более 100 раз и генерируя исключение, если оно терпит неудачу. В зависимости от вашей ситуации вы можете выбрать другой лимит.