基础篇——代码优化100条之(1—10)

1、从Map中取key和值

  当循环中只需要Map的主键时,迭代keySet()是正确的,但是,当需要主键和取值时,迭代entrySet()才是更高效的做法,比先迭代keySet()后再去get取值性能更加。

package com.zzb.test.admin;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * 当循环中只需要Map的主键时,
 * 迭代keySet()是正确的,但是,当需要主键和取值时,
 * 迭代entrySet()才是更高效的做法,比先迭代keySet()后再去get取值性能更加
 * Created by zzb on 2019/12/5 14:11
 */
public class TestOne {

    private static final Logger logger = LoggerFactory.getLogger(TestOne.class);
    public static void main(String[] args){
        Map<String,String> map = new HashMap<>();
        map.put("one","1");
        map.put("two","2");
        map.put("three","3");
        map.put("four","4");
        map.put("five","5");
        //反例
        for (String key:map.keySet()) {
            logger.info("key:{}",key);
            logger.info("value:{}",map.get(key));
        }
        //正例
        for (Map.Entry<String,String> entry:map.entrySet()) {
            logger.info("key:{}",entry.getKey());
            logger.info("value:{}",entry.getValue());
        }
    }
}

2、集合判空

  使用Collection.size()来检测空逻辑上是没有问题的,但是使用Collection.isEmpty()可以获得更好的性能。后者任何时候实现的时间复杂度都是0(1),而前者有时候实现的事件复杂度可能是0(n),如果需要判断是否为null,使用CollectionUtils

package com.zzb.test.admin;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;


/**
 * 使用Collection.size()来检测空逻辑上是没有问题的,
 * 但是使用Collection.isEmpty()可以获得更好的性能。后者任何时候实现的时间复杂度都是0(1),
 * 而前者有时候实现的事件复杂度可能是0(n)
 * 如果需要判断是否为null,使用CollectionUtils
 * Created by zzb on 2019/12/5 14:11
 */
public class TestOne {

    private static final Logger logger = LoggerFactory.getLogger(TestOne.class);
    public static void main(String[] args){
        List<String> list = null;

        if (CollectionUtils.isEmpty(list)) {
            logger.info("CollectionUtils空集合");
        }
        list = new ArrayList<>();
        if (list.size() == 0) {
            logger.info("空集合");
        }
        list.add("1");
        if (!list.isEmpty()) {
            logger.info("非空集合");
        }

    }

}

3、不要将集合对象传给自己

  由于某些方法要求参数在执行期间保持不变,因此将集合传递给自身可能会导致异常行为

package com.zzb.test.admin;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;


/**
 * 由于某些方法要求参数在执行期间保持不变,因此将集合传递给自身可能会导致异常行为
 * Created by zzb on 2019/12/5 14:11
 */
public class TestOne {

    private static final Logger logger = LoggerFactory.getLogger(TestOne.class);
    public static void main(String[] args){
        List<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        list.add("5");
        list.add("6");
        if (list.containsAll(list)) {
            logger.info("无意义,list.containsAll(list)总是返回true");
        }
        //性能差,不如list.clear()性能高
        list.removeAll(list);
//        list.clear();
        if (list.isEmpty()) {
            logger.info("移除自己之后");
        }

    }

}

4、初始化集合大小

  集合也是有大小限制的,每次扩容的时间复杂度很有可能是0(n),所以尽量初始化集合的大小,减少扩容的次数

package com.zzb.test.admin;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;


/**
 * 由于某些方法要求参数在执行期间保持不变,因此将集合传递给自身可能会导致异常行为
 * Created by zzb on 2019/12/5 14:11
 */
public class TestOne {

    private static final Logger logger = LoggerFactory.getLogger(TestOne.class);
    public static void main(String[] args){
        String[] strs = new String[]{"1","2","3","4","5","6"};
        //反例
        List<String> listBad = new ArrayList<>();
        for (String str:strs) {
            listBad.add(str);
            logger.info("每次添加都要进行扩容");
        }

        //正例
        List<String> list = new ArrayList<>(strs.length);
        for (String str:strs) {
            listBad.add(str);
            logger.info("初始化扩容完成,此时添加不需要扩容");
        }

    }

}

5、字符串的拼接使用StringBuilder

   其实直接拼接字符串,java在编译期会自动进行优化,但是在循环中的字符串拼接,java并不能自动进行优化,所以需要使用StringBuilder进行拼接

package com.zzb.test.admin;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;


/**
 * 字符串的拼接使用StringBuilder
 * 其实直接拼接字符串,java在编译期会自动进行优化,但是在循环中的字符串拼接,
 * java并不能自动进行优化,所以需要使用StringBuilder进行拼接
 * Created by zzb on 2019/12/5 14:11
 */
public class TestOne {

    private static final Logger logger = LoggerFactory.getLogger(TestOne.class);
    public static void main(String[] args){
        String str = "";
        //反例
        for (int i=0;i<10;i++) {
            str += i;
        }
        logger.info("循环拼接,java不能在编译期自动优化:{}",str);
        //正例
        String a = "1";
        String b = "2";
        String c = "3";
        String d = a + b + c;
        logger.info("直接拼接,java在编译期自动优化:{}",d);
        StringBuilder sb = new StringBuilder();
        for (int i=0;i<10;i++) {
            sb.append(i);
        }
        logger.info("使用StringBuilder循环拼接:{}",sb);
    }

}

6、list是否属于数组结构,判断是否可以随机访问

  ArrayList是数组结构,数组的随机访问效率更高;LinkedList是链表结构,其随机访问效率较低。

package com.zzb.test.admin;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.RandomAccess;


/**
 * list是否属于数组结构,判断是否可以随机访问
 * ArrayList是数组结构,数组的随机访问效率更高;LinkedList是链表结构,其随机访问效率较低
 * Created by zzb on 2019/12/5 14:11
 */
public class TestOne {

    private static final Logger logger = LoggerFactory.getLogger(TestOne.class);
    public static void main(String[] args){
        List arrayList = new ArrayList();
        List linkedList = new LinkedList();
        if (arrayList instanceof RandomAccess && !(linkedList instanceof RandomAccess)) {
            logger.info("数组结构的list实现RandomAccess,链表结构的list未实现RandomAccess");
        }
    }

}

7、Set集合中的Set.contains()方法效率更高

  List中的contains方法的时间复杂度大多为0(n),而HashSet中contains方法中的时间复杂度为0(1)

package com.zzb.test.admin;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;


/**
 * Set集合中的Set.contains()方法效率更高
 * List中的contains方法的时间复杂度大多为0(n),而HashSet中contains方法中的时间复杂度为0(1)
 * Created by zzb on 2019/12/5 14:11
 */
public class TestOne {

    private static final Logger logger = LoggerFactory.getLogger(TestOne.class);
    public static void main(String[] args){
        List list = new ArrayList();
        list.add("1");
        list.add("2");
        list.add("3");
        Set set = new HashSet(list);
        if (list.contains("1")) {
            logger.info("时间复杂度为0(n):{}",set.contains("1"));
        }
        if (set.contains("1")) {
            logger.info("时间复杂度为0(1):{}",set.contains("1"));
        }
    }
}

8、长整型常量后添加大写的L

  在使用长整型常量时,后面需要添加大写的L

private long val = 1L;

9、定义常量代替魔法值

  使用定义可读取的常量来替代魔法值,方便调试。-1,0,1不属于魔法值

package com.zzb.test.admin;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 定义常量代替魔法值
 * 使用定义可读取的常量来替代魔法值,方便调试。-1,0,1不属于魔法值
 * Created by zzb on 2019/12/5 14:11
 */
public class TestOne {

    private static final int COUNT = 10;

    private static final Logger logger = LoggerFactory.getLogger(TestOne.class);

    public static void main(String[] args){
        logger.info("定义常量,命名大写:{}",COUNT);
    }
}

10、初始化静态集合

  对于集合类型的静态成员变量,不要使用集合实现来赋值,应该使用静态代码块赋值

package com.zzb.test.admin;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * 初始化静态集合
 * 对于集合类型的静态成员变量,不要使用集合实现来赋值,应该使用静态代码块赋值
 * Created by zzb on 2019/12/5 14:11
 */
public class TestOne {
    //反例
    private static Map<String,String> mapNot = new HashMap<String,String>(){
        {
            put("ad","不使用");
            put("adc","静态块赋值");
        }
    };
    //正例
    private static Map<String,String> mapYes = new HashMap<String,String>();
    static{
        mapYes.put("ad","使用");
        mapYes.put("adc","静态块赋值");
    };

    private static final Logger logger = LoggerFactory.getLogger(TestOne.class);

    public static void main(String[] args){

        logger.info("集合初始化反例:{}",mapNot);

        logger.info("集合初始化正例:{}",mapYes);
    }
}

 

 

 

posted @ 2019-12-05 17:28  不浪小生  阅读(503)  评论(0编辑  收藏  举报