前言:因涉及數據庫的操作是單表並且用的mybatis自帶的api,因此優化從重構代碼開始(目標:從三秒優化到一秒,優化的是業務代碼)
一:對代碼進行分析(分析可優化項)
①:將代碼中字符串拼接由+號改爲append的方式(性能對比如下)
public static void main(String[] args) {
StopWatch stopWatch = new StopWatch("測試String");
stopWatch.start("a");
String adress;
adress = "江蘇省"+"大廟市"+"趟水縣"+"趙王鄉"+"小李村"+"李家莊"+"1002號";
System.err.println("adress:"+adress);
stopWatch.stop();
stopWatch.start("b");
String adress2;
StringBuffer st = new StringBuffer();
adress2 = st.append("江蘇省").append("大廟市").append("趟水縣").append("趙王鄉").append("小李村").append("李家莊").append("1002號").toString();
System.err.println("adress2:"+adress2);
stopWatch.stop();
System.err.println(stopWatch.prettyPrint());
}
②:數據量較小的情況下用foreach代替stream和for循環(數據量大的時候用stream有優勢)
public static void main(String[] args) {
List<Map<String, Object>> maps = new ArrayList<>();
for (int i = 0; i < 500; i++) {
maps.add(new HashMap<String,Object>(){{
put("IYPLX",0);
put("key1"+new Random().nextInt(1000),"張"+new Random().nextInt(1000));
}});
maps.add(new HashMap<String,Object>(){{
put("IYPLX",1);
put("key1"+new Random().nextInt(1000),"李"+new Random().nextInt(1000));
}});
}
StopWatch stopWatch = new StopWatch();
stopWatch.start("a");
Map<String, Object> hashMap = new HashMap<>();
List<Map<String, Object>> list11 = new ArrayList<>();
List<Map<String, Object>> list22 = new ArrayList<>();
for (Map<String, Object> map:maps) {
if(map.get("IYPLX").equals(0)){
list11.add(map);
}
if(map.get("IYPLX").equals(1)){
list22.add(map);
}
}
hashMap.put("XYCF",list11);
hashMap.put("ZYCF",list22);
System.err.println("list分組:"+hashMap.toString());
stopWatch.stop();
stopWatch.start("b");
Map<String, Object> hashMap2 = new HashMap<>();
Map<Object, List<Map<String, Object>>> iyplx = maps.stream().collect(Collectors.groupingBy(map -> map.get("IYPLX")));
hashMap2.put("XYCF",iyplx.get(0));
hashMap2.put("ZYCF",iyplx.get(1));
System.err.println("java8分組:"+hashMap2.toString());
stopWatch.stop();
System.err.println(stopWatch.prettyPrint());
}
③:對象轉化爲map的工具優化(通過分析性能排序從小到大 convert2Map->convertBean->PO2Map)
public static void main(String[] args) throws Exception {
MzzdPo1 mzzdPo1 = new MzzdPo1();
mzzdPo1.setCBM("222");
mzzdPo1.setCCS("11");
mzzdPo1.setCDH("123");
mzzdPo1.setCGG("23/s");
mzzdPo1.setCKC("44");
mzzdPo1.setCLS("55");
mzzdPo1.setCNL("34");
mzzdPo1.setCXM("zhan");
StopWatch stopWatch = new StopWatch("測試");
stopWatch.start("轉換map1");
Map<String, Object> map1 = convertBean(mzzdPo1);
stopWatch.stop();
stopWatch.start("轉換map2");
Map<String, Object> map2 = PO2Map(mzzdPo1);
stopWatch.stop();
stopWatch.start("轉換map3");
Map<String, Object> map3 = convert2Map(mzzdPo1);
stopWatch.stop();
System.err.println("map1"+map1.toString());
System.err.println("map2"+map2.toString());
System.err.println("map3"+map3.toString());
System.err.println(stopWatch.prettyPrint());
}
/**012530700 (3)*/
public static Map<String, Object> PO2Map(Object o) throws Exception{
Map<String, Object> map = new HashMap<String, Object>();
Field[] fields = null;
String clzName = o.getClass().getSimpleName();
log.info("類:"+o.getClass().getName());
fields = o.getClass().getDeclaredFields();
log.info("***"+clzName+"轉map開始****");
for (Field field : fields) {
field.setAccessible(true);
String proName = field.getName();
Object proValue = field.get(o);
map.put(proName.toUpperCase(), proValue);
log.info("key:"+proName+"value:"+proValue);
}
log.info("***"+clzName+"轉map結束****");
return map;
}
/** 000054800 (1)*/
private static <T> Map<String, Object> convert2Map(T t) {
Map<String, Object> result = new HashMap<String, Object>();
Method[] methods = t.getClass().getMethods();
try {
for (Method method : methods) {
Class<?>[] paramClass = method.getParameterTypes();
if (paramClass.length > 0) { // 如果方法帶參數,則跳過
continue;
}
String methodName = method.getName();
if (methodName.startsWith("get")) {
Object value = method.invoke(t);
result.put(methodName.substring(3,methodName.length()), value);
}
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
return result;
}
/**009706100 (2)*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static Map convertBean(Object bean)
throws IntrospectionException, IllegalAccessException, InvocationTargetException {
Class type = bean.getClass();
Map returnMap = new HashMap();
BeanInfo beanInfo = Introspector.getBeanInfo(type);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (int i = 0; i< propertyDescriptors.length; i++) {
PropertyDescriptor descriptor = propertyDescriptors[i];
String propertyName = descriptor.getName();
if (!propertyName.equals("class")) {
Method readMethod = descriptor.getReadMethod();
Object result = readMethod.invoke(bean, new Object[0]);
if (result != null) {
returnMap.put(propertyName, result);
} else {
returnMap.put(propertyName, "");
}
}
}
return returnMap;
}
④:循環中創建對象由new改爲clone
public static void main(String[] args) {
StopWatch stopWatch = new StopWatch("測試對象");
stopWatch.start("a");
List<Object> objects = new ArrayList<>();
for (int i = 0; i <50; i++) {
MzzdPo mzzdPo = new MzzdPo();
mzzdPo.setId(i+"");
mzzdPo.setName("張"+i);
objects.add(mzzdPo);
}
System.err.println(objects.toString());
stopWatch.stop();
stopWatch.start("b");
List<Object> objects2= new ArrayList<>();
for (int i = 0; i <50; i++) {
MzzdPo mzzdPo = MzzdPo.getInstance();
mzzdPo.setId(i+"");
mzzdPo.setName("張"+i);
objects2.add(mzzdPo);
}
System.err.println(objects2.toString());
stopWatch.stop();
System.err.println(stopWatch.prettyPrint());
}
MzzdPo 的對象要實現Cloneable接口
@Slf4j
@Data
public class MzzdPo implements Serializable,Cloneable {
private String id;
private String name;
private String age;
private static MzzdPo mzzdPo = new MzzdPo();
public static MzzdPo getInstance() {
try {
return (MzzdPo)mzzdPo.clone();
}catch (Exception e){
log.error("clone 創建對象失敗,走的是new");
}
return new MzzdPo();
}
}
⑤:總結:經過上面的四個方面優化,將代碼的性能由3秒優化到1秒,當然其他方面也可優化,根據實際情況去具體對待吧