在我遇到循环复杂性问题的方法中,我有一个if-else语句块。我已经尝试过使用switch语句,但是问题仍然存在。
if (fileName.startsWith(HwErrorsEtlConstants.MR_RAW_GRADIENT_ERRORS)) {
method1()...
} else if (fileName.startsWith(HwErrorsEtlConstants.MR_RAW_PFEI_ERRORS)) {
method2()...
} else if (fileName.startsWith(HwErrorsEtlConstants.MR_RAW_RFAMP_ERRORS)) {
method3()...
} and so on...
public static void method1(IOutputWriter writer, String fileName, InputStream fileInputStream) throws IOException {
//logic for the method
}
答案 0 :(得分:3)
编辑:如前所述,您已经检查了Exception
个可以在您的方法中和自变量引发的内容。由于Runnable
并没有声明可以抛出Exceptions
并且不接受任何参数,因此您必须创建自己的FunctionalInterface
(单击here来查看它们的含义)确实是):
public interface ThrowingRunnable {
void run(IOutputWriter writer, String fileName, InputStream fileInputStream) throws IOException;
}
然后,您只需在下面我先前建议的代码中将Runnable
替换为ThrowingRunnable
,就可以了。
您可以创建HwErrorsEtlConstants
到特定方法的映射(使用Java 8):
static final Map<String, Runnable> MAPPING;
static {
Map<String, Runnable> temp = new HashMap<>();
temp.put(HwErrorsEtlConstants.MR_RAW_GRADIENT_ERRORS, this::method1);
temp.put(HwErrorsEtlConstants.MR_RAW_PFEI_ERRORS, this::method2);
temp.put(HwErrorsEtlConstants.MR_RAW_RFAMP_ERRORS, this::method3);
MAPPING = Collections.unmodifiableMap(temp);
}
然后在您的方法中,可以使用Java 8中也引入的Stream
:
// Optional indicates a potentially absent value, it's just a wrapper around a Runnable
Optional<Runnable> optional = MAPPING
// create a Stream from the entries
.entrySet().stream()
// keep the items that match the condition and drop every other
.filter(e -> filename.startsWith(e.getKey()))
// we had Map.Entry<String, Runnable>, but now we only need the value e.g. the Runnable
.map(Map.Entry::getValue)
// short circuit, e.g. we only want the first value that matches
.findFirst();
// checks if anything is present, this is used as the MAPPING "could" be empty
if(optional.isPresent()) {
// unpack the value and call it with arguments
optional.get().run(aWriter, someFileName, anInputStream);
} else {
// nothing matched, throw error or log etc.
}
尽管如上所述,您当前的解决方案确实不错,但我想您正在使用Sonar进行代码分析。有时,Sonar只会产生误报,因此您也可以放心地忽略它们。
进一步阅读以帮助您理解Java 8:
答案 1 :(得分:2)
cyclomatic complexity是一个问题:确实是周期。
然后使用不面向对象的if / switch对属性进行分割。它还可能违反关注点分离:拥有许多处理完全不同的较小方面的方法。
如果字段数较大,并且行数较大,请考虑提取处理一个方面的类。
为降低循环复杂性,请检查以控制调用者的流程,同一呼叫的重复,实用的重复代码。然后尝试(重新)移动循环。 最好是可以将各个周期放在一起的时间;并处理列表/集合/流。
答案 2 :(得分:1)
您可以使用谓词和函数功能接口通过Java 8方法解决此问题。您必须通过谓词放置所有条件,然后在Function中添加条件匹配时需要执行的实现。
Map<Predicate,Function<String,String>> map = new HashMap<>();
Predicate<String> p = (fileName)->fileName.startsWith(HwErrorsEtlConstants.MR_RAW_GRADIENT_ERRORS);
Function<String,String> method = (input)->{ return "output";};
map.put(p,method);
Optional<String> result =
map.entrySet()
.stream()
.filter(entry->entry.getKey().test(fileName))
.map(entry->entry.getValue().apply())
.findFirst();
OR
map.entrySet()
.stream()
.filter(entry->entry.getKey().test(fileName))
.forEach(entry->entry.getValue().apply());