Java 减少圈复杂度,多个if语句
如果我没有包括这些条件,我还有很多其他条件。我如何重构它以降低圈复杂度Java 减少圈复杂度,多个if语句,java,complexity-theory,reduce,Java,Complexity Theory,Reduce,如果我没有包括这些条件,我还有很多其他条件。我如何重构它以降低圈复杂度 if (ONE.equalsIgnoreCase(eachTag.getNodeName())) { myclassDto.setOne(formatter .getElementValueAfterNullCheckWithTrim((Element) eachTag)); } else if (TWO.equalsIgnoreCase(eachTag.getNodeName())) {
if (ONE.equalsIgnoreCase(eachTag.getNodeName()))
{
myclassDto.setOne(formatter
.getElementValueAfterNullCheckWithTrim((Element) eachTag));
}
else if (TWO.equalsIgnoreCase(eachTag.getNodeName()))
{
myclassDto.setTwo(formatter
.getElementValueAfterNullCheckWithTrim((Element) eachTag));
}
else if (THREE.equalsIgnoreCase(eachTag.getNodeName()))
{
myclassDto.setThree(formatter
.getElementValueAfterNullCheckWithTrim((Element) eachTag));
}
else if (FOUR.equalsIgnoreCase(eachTag.getNodeName()))
{
myclassDto.setFour(formatter
.getElementValueAfterNullCheckWithTrim((Element) eachTag));
}
else if (FIVE.equalsIgnoreCase(eachTag.getNodeName()))
{
myclassDto.setFive(formatter
.getElementValueAfterNullCheckWithTrim((Element) eachTag));
}
else if (SIX.equalsIgnoreCase(eachTag.getNodeName()))
{
myclassDto.setSix(formatter
.getElementValueAfterNullCheckWithTrim((Element) eachTag));
}
如何在java中降低此函数的圈复杂度?如果您:
- 使用switch语句
- 预先提取getNodeName()的值
- 预先提取getElementValueAfterNullCheckWithTrim()返回的值
String value = formatter.getElementValueAfterNullCheckWithTrim((Element) eachTag); String nodeName = eachTag.getNodeName(); switch (nodeName) { case ONE: myclassDto.setOne(value); break; case TWO: myclassDto.setTwo(value); break; ... }
myclassDto.setValue(nodeName, value)
我将定义字符串到它们对应的函数的映射。这可能是静态的 然后,您可以循环映射,找到合适的映射(
filter
)并应用该函数
private static final Map<String, BiConsumer<MyClassDto, Element>> MAPPING = new HashMap();
static
{
mapping.put(ONE, MyClassDto::setOne);
mapping.put(TWO, MyClassDto::setTwo);
//...
mapping.put(SIX, MyClassDto::setSix);
}
//...
MAPPING.entrySet().stream()
.filter(pair -> pair.getKey().equalsIgnoreCase(eachTag.getNodeName()))
.map(Map.Entry::getValue)
.forEach(func -> func.accept(
myClassDto,
formatter.getElementValueAfterNullCheckWithTrim((Element) eachTag)
));
private静态最终映射=newhashmap();
静止的
{
mapping.put(一个,MyClassDto::setOne);
put(两个,MyClassDto::setTwo);
//...
mapping.put(六个,MyClassDto::setSix);
}
//...
MAPPING.entrySet().stream()
.filter(pair->pair.getKey().equalsIgnoreCase(eachTag.getNodeName())
.map(map.Entry::getValue)
.forEach(函数->函数接受)(
myClassDto,
formatter.getElementValueAfterNullCheckWithTrim((元素)eachTag)
));
您可能想考虑<代码>映射可以包含不同的密钥,这些代码被代码> >均衡器> /代码>(例如“AAA”和“AAA”)同等对待。
一种解决方案是使用
findFirst().ifPresent()
代替forEach
(如所建议),但这可能会掩盖一些错误情况,因此请谨慎使用。考虑到DTO的实际架构,重构部分非常重要。当我使用switch时,将复杂性从19降低到17。但是需要减少到10。正如我在回答中所说,使用开关
与使用if
一样“复杂”。它只是更具可读性。那么重构DTO呢?如果您的DTO在接受数据方面效率不高,即它有100套***()方法,我怀疑您会得到一个较低的复杂度数字。这可能是我的方法,但您不能以相同的结果执行forEach
;可能会触发多个映射,并调用多个BiConsumer
。因此,findFirst().ifPresent()
。另外,getNodeName
可能在流之外。@daniu我的问题是,findFirst
可能会掩盖一些难以发现的bug。如果有两个具有不同大小写字符串的映射(例如,“AAA”和“AAA”),并且假定HashMap
没有可预测的迭代顺序,则使用findFirst
可能会导致在每个函数之间来回交换。这将是难以置信的难以追踪。如果你想确保没有两个“相等”的映射,最好编写一个函数来迭代键并检查重复项。同意,但如果你在代码中添加“aaa”和“aaa”,你将调用这两个BiConsumer
s。如果他们将匹配项添加到具有唯一性约束的数据库中,则将失败。我宁愿使用findFirst
和LinkedHashMap
进行映射(我认为这提供了确定性迭代)。对于OP的简单案例来说,这些都无关紧要;)@大牛,没错。在这种情况下,我的示例将快速失败,而您的示例将是故障安全的。我会马上知道出了什么事,而你也会幸灾乐祸地不知道