最近做的项目,一个接口操作十几张表,速度很慢,BOSS让我优化。
我打开一看,吓我一跳,循环嵌套一层又一层,循环里还CRUD,这不慢就有鬼了。
整理完思路,把需要查数据库的一起查出来,再做处理。
由于是很多查表是根据某几个字段查的,现在一起查出来需要匹配。
例如:从数组B中找到和数据A中有关联的数据。
第一种方案是嵌套循环,O(n*n)时间复杂度太高pass掉。
想到利用散列表,Java的散列表就是Map啊,各种缓存都用它,时间复杂度是O(1),很满意。
于是乎,出现了List转Map<String,List>的需求。
到处都用这个方法,复制来复制去,冗余太多,写一个工具类更胜一筹。
反射吧,听说效率不高,我也没测试过,不管啦,别出心裁用方法引用试试。
对了,Java8的Stream流有现成的,最开始没想到查API。
贴代码,为了省事都写在一个类里了。
package com.bn;
import com.bn.springcloud.entities.Payment;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
/**
* @author wty
* @date 2020/10/9 22:18
*/
public class ListToMapUtil {
public static void main( String[] args ) {
List<Payment> list = new ArrayList<>( );
list.add( new Payment( 1L,"200" ) );
list.add( new Payment( 2L,"200" ) );
list.add( new Payment( 3L,"300" ) );
Map< String, List< Payment > > stringListMap = listToMap( list, Payment :: getSerial,Payment::getSerial );
System.err.println(stringListMap );
}
@SafeVarargs
public static <V> Map<String, List<V>> listToMap( List<V> data, Function<V, String>... func) {
Map<String, List<V>> map = new HashMap<String, List<V>>();
for (V rData : data) {
String key = "";
for ( Function<V, String> function : func) {
key += function.apply(rData);
}
List<V> list = map.get(key);
if (list == null || list.size() < 1) {
List<V> MHDList = new ArrayList<V>();
MHDList.add(rData);
map.put(key, MHDList);
} else {
list.add(rData);
}
}
return map;
}
}
输出:{300300=[Payment(id=3, serial=300)], 200200=[Payment(id=1, serial=200), Payment(id=2, serial=200)]}
分析一下这个方法的时间复杂度
首先遍历List是O(n),里面有一个循环,目前需求最多三个字段分组,是O(3n),再加上散列表查询的时间复杂度O(3n+1),去掉常数项和低阶项,最后时间复杂度是O(n)。
So,这个接口优化完应该会快不少。
Over!