来自PMD的Java流while循环异常警告
在以下代码中,我创建了一个新ID,检查它是否存在,如果它是唯一的,则返回它:来自PMD的Java流while循环异常警告,java,java-stream,static-analysis,pmd,Java,Java Stream,Static Analysis,Pmd,在以下代码中,我创建了一个新ID,检查它是否存在,如果它是唯一的,则返回它: private String generateNewId(List<Item> items) { do { String newId = ... // generateNewId from another method if (items.stream.noneMatch(i -> i.getId().equals(newId))) {
private String generateNewId(List<Item> items) {
do {
String newId = ... // generateNewId from another method
if (items.stream.noneMatch(i -> i.getId().equals(newId))) {
return newId;
}
} while(true);
}
private String generateNewId(列表项){
做{
字符串newId=…//generateNewId来自另一个方法
if(items.stream.noneMatch(i->i.getId().equals(newId))){
返回newId;
}
}虽然(正确);
}
但是,我发现PMD异常:
- 发现变量“newId”的“DD”-异常
- 发现变量“newId”的“DU”异常
newId
变量移出循环,但后来我得到了错误:lambda中使用的变量应该是final或实际上是final
如何重构代码以消除这些异常?或者我应该将这些警告抑制为误报吗?您正在看到DD异常,因为当if条件计算为false时,变量
newId
在do{}while(true)
循环中被重新定义
然而,我认为DU异常是假阳性。在这种情况下,newId
始终至少使用一次:
- 如果项目列表为空,则返回
newId
- 如果项目列表不为空,则
用于关闭newId
nonMatch
noneMatch
的语义。如果将noneMatch
替换为anyMatch
,则这将是一个真正的DU异常
DD和DU异常通常很难修复,因为它们指出了更高层次的设计问题。在这种情况下,问题不直接在于变量newId
本身,而是使用do{}while(true)
,这可能导致infinte循环,因为您忽略了无法生成新的唯一id的情况
解决此问题的一种方法是解决此问题:
private String generateNewId(列表项){
return Stream.generate(this::getRandomId)
.限额(100)
.filter(id->isNew(id,items))
.findAny()
.orelsetrow(()->new NoSuchElementException(“未能生成唯一id”);
}
私有字符串getRandomId(){
返回“4”;//由公平掷骰选择。
//保证是随机的。
}
私有布尔值isNew(字符串id,列表项){
返回items.stream().noneMatch(item->id.equals(item.getId());
}
此解决方案通过尝试最多生成100次新id并在失败时抛出异常来解决无限循环问题。根据您的情况,您可能会选择不同的限制。您正在看到DD异常,因为当if条件计算为false时,变量
newId
在do{}while(true)
循环中被重新定义
然而,我认为DU异常是假阳性。在这种情况下,newId
始终至少使用一次:
- 如果项目列表为空,则返回
newId
- 如果项目列表不为空,则
用于关闭newId
nonMatch
noneMatch
的语义。如果将noneMatch
替换为anyMatch
,则这将是一个真正的DU异常
DD和DU异常通常很难修复,因为它们指出了更高层次的设计问题。在这种情况下,问题不直接在于变量newId
本身,而是使用do{}while(true)
,这可能导致infinte循环,因为您忽略了无法生成新的唯一id的情况
解决此问题的一种方法是解决此问题:
private String generateNewId(列表项){
return Stream.generate(this::getRandomId)
.限额(100)
.filter(id->isNew(id,items))
.findAny()
.orelsetrow(()->new NoSuchElementException(“未能生成唯一id”);
}
私有字符串getRandomId(){
返回“4”;//由公平掷骰选择。
//保证是随机的。
}
私有布尔值isNew(字符串id,列表项){
返回items.stream().noneMatch(item->id.equals(item.getId());
}
此解决方案通过尝试最多生成100次新id并在失败时抛出异常来解决无限循环问题。根据您的情况,您可以选择不同的限制。与问题无关,但您不应该生成这样的ID。您拥有的项目越多,所需时间越长(生成n个ID需要O(n^2)个步骤)。您应该使用UUID,从技术上讲,UUID并不能避免ID冲突,但它们太不可能了,这无关紧要。@Clashsoft我知道,不幸的是,这是客户端的一个要求-保持向后兼容性。我更喜欢使用UUID,我只是不能…与问题无关,但你不应该生成这样的ID。您拥有的项目越多,所需时间越长(生成n个ID需要O(n^2)个步骤)。您应该使用UUID,从技术上讲,UUID并不能避免ID冲突,但它们太不可能了,这无关紧要。@Clashsoft我知道,不幸的是,这是客户端的一个要求-保持向后兼容性。我更喜欢使用UUID,我就是不能。。。