这是个人在写代码时的一个优化心得,可以让代码更清晰,更具可维护性
if 嵌套优化
有时候我们会看到类似这样的代码:
if (a = b) {
if (c = d) {
if (e = f) {
// 代码执行逻辑
.....
}
}
}
这种代码嵌套越多越是难以维护,在某些情况下我们可以更改成这样:
if (a != b) {
return;
}
if (c != d) {
return;
}
if (e != f) {
return;
}
// 代码执行逻辑
...........
这样的代码就非常清晰了,但是在某些情况下我们不能直接return还需要将代码继续执行下去,例如:
private void funName() {
// 当这里执行完毕后
if (a = b) {
if (c = d) {
if (e = f) {
// 代码执行逻辑
.....
}
}
}
// 继续往下执行
// 第二层代码执行逻辑
.........
}
此时我们可以封装一层方法将来处理上面那层代码逻辑例如:
private void funName() {
InvokedFun()
// 继续执行代码逻辑
.........
}
private void InvokedFun() {
if (a != b) {
return;
}
if (c != d) {
return;
}
if (e != f) {
return;
}
// 代码执行逻辑
...........
}
基本以上两种技巧如果应用得当代码会清晰很多,一定程度商可以帮自己理清思路,并降低bug 出现的几率。
2022年11月25日 补充
在写代码的过程中可能会出现这样一种情况:
private void funName(Map<Integer,Entity> entityMap,Integer id) {
if (entityMap != null) {
Entity entity = entityMap.get(id)
if (entity != null) {
// 执行代码逻辑A
.......
}
} else {
Entity entity = new Entity()
// 设置相关属性
.........
// 执行代码逻辑A
.........
entityMap.put(id,entity)
}
}
上面的代码逻辑A 执行的是完全相同的代码,代码流程问题不得不写两次或者重新写一个方法进行封装,可以改成下面这种方式:
private void funName(Map<Integer,Entity> entityMap,Integer id) {
Entity entity = entityMap.get(id)
if (entityMap == null) {
Entity entity = new Entity()
// 设置相关属性
.........
entityMap.put(id,entity)
}
// 执行代码逻辑A
.........
}
因为代码逻辑A 在为空的情况下和不为空的情况下都必须执行,而这里的if else 只是为了保证数据不为空,这时候这样处理代码会清晰简洁很多
for 循环嵌套优化
同样的道理,for 循环也会产生相同的问题,不断嵌套导致代码不清晰,例如:
List<Entity> demo = new ArrayList<>;
for(int i = 0;i < demo.size(); i++) {
// 从数据库或其他地方获取数据
List<EntityItem> entityItemList = entityMapper.listByParentId(demo.getId());
for (int n = 0; n < entityList.size(); i++){
EntityItem entityItem = entityItemList.get(i);
// 代码执行逻辑
...........
}
}
两层代码嵌套看起来没有那么乱,但是如果从第三层嵌套开始代码清晰度就会直线下降,这时候可以这样写:
List<Entity> demo = new ArrayList<>;
List<EntityItem> entityItemListAll = new ArrayList();
for(int i = 0;i < demo.size(); i++) {
// 从数据库或其他地方获取数据
List<EntityItem> entityItemList = entityMapper.listByParentId(demo.getId());
entityItemListAll.addAll(entityItemList);
}
for (int n = 0; n < entityList.size(); i++){
EntityItem entityItem = entityItemList.get(i);
// 代码执行逻辑
...........
}
算是以空间换代码整洁度,但是自己想想,这里真正占用到内存的只有entityItemListAll 的创建,因为即使用entityItemListAll.addAll(entityItemList);将数据添加到新的list 当中,其实只是将原list 的每个数据的内存地址进行了拷贝,并不会新建对象,为此我做了以下测试:
List<String> listA = new ArrayList<>();
listA.add("1");
listA.add("2");
listA.add("3");
List<String> listB = new ArrayList<>();
listB.addAll(listA);
for (int i = 0; i < listA.size(); i++) {
String item = listA.get(i);
System.out.println(System.identityHashCode(item));
}
for (int i = 0; i < listB.size(); i++) {
String item = listB.get(i);
System.out.println(System.identityHashCode(item));
}
我使用了以下代码对内存地址进行了打印:
打印内存地址参考:java打印对象内存地址 | kennedyhan
System.identityHashCode(item)
最终发现listB中的内存地址并没有发生改变:
Connected to the target VM, address: '127.0.0.1:62988', transport: 'socket'
93122545
2083562754
1239731077
93122545
2083562754
1239731077
Disconnected from the target VM, address: '127.0.0.1:62988', transport: 'socket'
Process finished with exit code 0
所以这里并没有占用新的对象,而创建一个List 个人认为成本可以忽略不计,因为方法一旦完结则方法内的所有对象将会被gc 回收。
2022年12月20日 补充
for 循环嵌套优化技巧(二)
还有一种情况如下所示:
for (Entity entity: entityList) {
for (SearchEntity search: searchEntitylist) {
if (entity.seatchId == search.id) {
// 执行任务流程
......
}
}
}
可以看出,每次entity 循环都会遍历一次SearchEntity这是没必要的,可以通过以下方式降低循环次数,并提高代码清晰度:
Map<Long,SearchEntity> searchEntityMap = new HashMap();
for (SearchEntity search: searchEntitylist) {
searchEntityMap.put(search.id,search);
}
for (Entity entity: entityList) {
SearchEntity search = searchEntityMap.get(entity.searchId);
if (search == null) {
continue;
}
// 执行业务逻辑
.......
}