JAVA开发必会的简单优化方式(易学)

40 篇文章 1 订阅

1,使用普通for循环遍历,应实现减少对变量的重复计算
// 例如
for(int i=0;i<list.size();i++)

// 改为
for(int i=0,len=list.size();i<len;i++)  
2,使用equals进行空字符判断时,应避免空指针异常(NullPointerException)
  String myqxin = null;
  // 列如
  if (myqxin.equals(""))
  
  // 改为
  if("".equals(myqxin)) 
3,尽量避免不必要的创建
// 列如:
A a = new A();
if(i==1){
list.add(a);
}

// 改为:
if(i==1){
A a = new A();
list.add(a);
}
4,尽量使用移位代替 a/b 和 a*b
		int a = 12;
		// 列如
        System.out.println(a/2);
		// 改为
        System.out.println(a>>1);

	 	int b = 12;
		// 例如
        System.out.println(b*4);
		// 改为
        System.out.println(b<<2);
5,尽量确定StringBuffer的容量
// 例如
StringBuffer buffer = new StringBuffer(501);

说明:StringBuffer 的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建 StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。

6,尽量使用System.arraycopy ()代替通过来循环复制数组
		String[] arr = {"1","2","3"};
        String[] brr = new String[arr.length];
        System.arraycopy(arr,0,brr,0,arr.length);	
 		System.out.println(Arrays.toString(brr));	// 结果 [1,2,3]

参数1:源数组,参数2:源数组起始位置,参数3:目标数组,参数4:目标数组起始位置,参数5:复制的长度

注意:参数2起始的位置,后面的长度,要小于等于参数5的复制长度,例如以下

	String[] arr = {"1","2","3"};
    String[] brr = new String[arr.length];
   	// System.arraycopy(arr,1,brr,0,arr.length);  抛出异常,ArrayIndexOutOfBoundsException
    System.arraycopy(arr,1,brr,0,arr.length-1);
	System.out.println(Arrays.toString(brr));	// 结果 [1,2,null]
7,如果用到双层for循环,尽量使用Map集合进行优化
		ArrayList<User> ulist = new ArrayList<>();
        User u1 = new User("1", "冷言1");
        User u2 = new User("2", "冷言2");
        User u3 = new User("3", "冷言3");
        User u4 = new User("4", "冷言4");
        ulist.add(u1);
        ulist.add(u2);
        ulist.add(u3);
        ulist.add(u4);
        ArrayList<Person> plist = new ArrayList<>();
        Person p1 = new Person("1", "男");
        Person p2 = new Person("2", "女");
        Person p3 = new Person("3", "女");
        Person p4 = new Person("4", "男");
        plist.add(p1);
        plist.add(p2);
        plist.add(p3);
        plist.add(p4);
		// 例如
        for (User u : ulist) {
            for (Person p : plist) {
               if(u.getUid().equals(p.getPid())){
                   u.setSex(p.getSex());
               }
            }
        }
        for (User user : ulist) {
            System.out.println(user);
        }
		// 展示结果为
		// User{uid='1', name='冷言1', sex='男'}
		// User{uid='2', name='冷言2', sex='女'}
		// User{uid='3', name='冷言3', sex='女'}
		// User{uid='4', name='冷言4', sex='男'}

		//改为
		 Map<String,Person> list2Map = 					     plist.stream().collect(Collectors.toMap(Person::getPid, Function.identity()));
        for (User user : ulist) {
            Person person = list2Map.get(user.getUid());
            if(person != null){
                user.setSex(person.getSex());
            }
        }

		// 展示结果为
		// User{uid='1', name='冷言1', sex='男'}
		// User{uid='2', name='冷言2', sex='女'}
		// User{uid='3', name='冷言3', sex='女'}
		// User{uid='4', name='冷言4', sex='男'}
8,使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一致、长度为 0 的空数组。
		ArrayList<String> list = new ArrayList<>();
        list.add("冷言");
        list.add("魅言倾馨");
        // 例如
        Object[] array = list.toArray();
		System.out.println(Arrays.toString(array));
        // 改为
        String[] array1 = list.toArray(new String[0])
        System.out.println(Arrays.toString(array1));

说明:使用 toArray 带参方法,数组空间大小的 length,
1) 等于 0,动态创建与 size 相同的数组,性能最好。
2) 大于 0 但小于 size,重新创建大小等于 size 的数组,增加 GC 负担。
3) 等于 size,在高并发情况下,数组创建完成之后,size 正在变大的情况下,负面影响与 2 相同。
4) 大于 size,空间浪费,且在 size 处插入 null 值,存在 NPE 隐患

9,使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历。
		HashMap<Integer, String> map = new HashMap<>();
        map.put(1,"冷言");
        map.put(2,"魅言倾馨");
        // 例如
        for (Integer integer : map.keySet()) {
            System.out.println(integer);
        }
        // 改为
        for (Map.Entry<Integer, String> entry : map.entrySet()) {
            System.out.println(entry.getKey());
        }

说明:keySet 其实是遍历了 2 次,一次是转为 Iterator 对象,另一次是从 hashMap 中取出 key 所对应的
value。而 entrySet 只是遍历了一次就把 key 和 value 都放到了 entry 中,效率更高。如果是 JDK8,使用
Map.forEach 方法。

10,使用条件分组或者switch来代替多个if-else语句

我相信大部分都看到过好多if-else吧,这样也是会影响性能的。如果在for、while等循环语句使用这一长串的if-else,情况会变得更糟。
如果我们的业务逻辑中有很多的条件,我们可以尝试着将条件分组并且返回一个布尔值,然后在将其用于if语句,下面看一个示例

// 错误示范
if(condition1) {
	if(condition2){
	if(condition3 || condition4) { 
	 System.out.println(1);
	}
	else {
	System.out.println(2);
      }
   }
}


// 优化改正
boolean result = (condition1 && condition2) && (condition3 || condition4)
if (result) {
 System.out.println(1);
} else {
 System.out.println(2);
}
11,使用PreparedStatement而不是Statement

现在应该比较少用JDBC API进行SQL查询了,但是我觉得还是有必要了解一下。
对于参数化查询,PreparedStatement比Statement更有优势,因为PreparedStatement对象被编译一次并执行多次。Statement对象在每次被调用时都会被编译和执行。
此外,PreparedStatement对象是安全的,可以避免SQL注入攻击。

12,尽可能使用基本类型

因为基本类型存储在栈内存中,而对象存储在堆内存中。如果可以的话,我们应该尽可能使用基本类型而非对象,因为栈内存的访问速度比堆内存快。

因此在某些情况下,定义一个变量或者数组,我们可以使用int而非Integer,double而非Double。

13,避免使用+来拼接字符串

从JDK5开始,Java编译器就做了优化,使用+号拼接字符串,编译器编译后实际就自动优化为使用StringBuilder。

而且String是final类,用String创建的对象无法重复使用。因此,如果我们需要连续拼接,使用+号拼接字符串将导致创建多个String对象,从而会占用更多的堆内存。

一般来说,当字符串不多的时候,+号与StringBuilder的拼接效率其实相差无几;但是如果涉及到单线程循环拼接的时候,我们最好还是使用StringBuilder以保证性能上的优化。


	String str = "myqxi";
    for (int i = 0; i < count; i++) {
        str = str + "-" + i;
    }


// 改正示例
	StringBuilder stringBuilder = new StringBuilder("myqxin");
    for (int i = 0; i < count; i++) {
        stringBuilder.append("-");
        stringBuilder.append(i);
    }

小结:

以上只是我目前所接触到的,肯定还有很多啊,欢迎交流交流

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子非我鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值