降低圈复杂度
需求:
代码优化:最近公司要求对代码做整改,其中就涉及到圈复杂度。以前也就接触过时间复杂度,所以不得不去搜一波资料。
简述:
1. 概念:
圈复杂度(Cyclomatic complexity,CC)也称为条件复杂度,是一种衡量代码复杂度的标准,其符号为V(G)。简而言之,也就是统计代码中条件判断的数量。
2. 影响因素:
- if 语句
- while 语句
- for 语句
- case 语句
- catch 语句
- and 和 or 布尔操作
- ? : 三元运算符
3. 计算方式:
**V (G) ** =P +1
P代表代码中条件判断数量,也就是上面影响因素存在的个数,1代表正常顺序的圈复杂度
例:
下面圈复杂度为2:
while ("0".equals(a)){
if (b != null){
c++;
}
}
4. 注意 :
- if (a == null && b != null) 圈复杂度为2,因为有两个判断,所以当你处心积虑把两个if条件组合时,圈复杂度并没有改变,改变的是认知复杂度。
- if-else和if圈复杂度都是1,不要想着只留if去掉else,结果并没有改变
3. 条件嵌套和提出不影响圈复杂度计算,例如把if里面的for循环提到外面,结果圈复杂度还是2
4. if转换成三元运算符不影响圈复杂度
5. 降低圈复杂度的目的是为了优化代码,降低维护成本,不要为了降低而强行将代码抽取复杂化
6. 千万不要改动原来逻辑
优化方法:
目前只用了几种方法,下面是几个优化的例子
-
尽量使用封装好的util类
//字符串为空判断 //改前: if (a == null || a.length() == 0){ b ++; } //改后: if (StringUtil.isEmpty()){ b ++; }
//集合空判断(List\Map\Set) //改前: if (list == null || list.size() == 0){ b ++; } //改后: if (CollectionUtils.isEmpty){ b ++; }
//关各种流 //改前: if (stream != null){ try { stream.close(); } catch (IOException e) { e.printStackTrace(); } } //改后: IOUtils.closeQuietly(stream)
-
switch/case转成map
//改前: switch (a){ case 1: b = "f"; break; case 2: b = "g"; break; default: break; } //改后: Map<Integer,String> map = new HashMap<>(); map.put(1,"f"); map.put(2,"g"); b = map.get(a);
-
提炼函数
//改前: if ( b == null ){ a = 1; }else{ a= 4; } //改后: public static <T> T getValueByCondition(boolean condition,T valueOfTrue,T valueOfFalse){ if (condition){ return valueOfTrue; }else { return valueOfFalse } } a = getValueByCondition(b == null,1,4);