5个优化java代码的性能的tips

大多数时候,应用性能的优化不是必需的,但是本文包含的5种办法非常简单,可以在代码开发期间低成本得采纳,以防止java程序变慢以及占用更多的资源。

尽可能于设置HashMap和ArrayList的大小

HashMap和ArrayList等基于数组的结构,都存在一个问题,就是当不断添加数据超过阈值时,就会触发resize扩容操作,尽管这些类的大多数操作都很快,比如ArrayList.get(index)是 o(1)时间复杂度,但是resize操作的时间都是O(n),并且可能会出现很多次的重复。

ArrayList 默认的容量为10,当数据超过10时候,就会触发扩容,扩容操作为new_capacity = old_capacity * 2;此时会变成20大小的数组。

假如我们需要添加500个元素到ArrayList中,那么它的内部表现是这样的:10->20->40->80->160->320->640. 总共产生了6次扩容操作,每次操作都会复制一次整个数组,同时最后产生了一个640大小的数组,而其实我们只需要500大小的数组,这里就导致了21%空间的浪费。

如果我们能明确值存储500个对象,就可以将ArrayList大小直接设定为500。

ini 复制代码
List<Object> list = new ArrayList(500);

这样就可以避免使用过程中的扩容操作以及浪费的45%内存(20大小的数组,只使用了11个位置,浪费了9个)。

HashMap的扩容情况比ArrayList更严重,因为它含有一个扩容因子参数,默认为0.75,当数据量达到容量的0.75时就会触发扩容。

因为有扩容因子的存在,对于HashMap大小的设置会有一点麻烦,推荐使用Guava的Maps.newHashMapWithExpectedSize(int size)方法,该方法内置了预期大小的计算.

ini 复制代码
Map<String> map = Maps.newHashMapWithExpectedSize(24);

对HashMap的复合key使用实体类包装

当我们在HashMap中使用复合的String作为key时,使用一个实体类可以加快速度和避免内存分配。

错误方式

ini 复制代码
    String[] prefixes;
    String[] suffixes;
    Map<String, Object> concatMap;
    // 获取数据
      for (int i = 0; i < prefixes.length; ++i) {
        concatMap.get(prefixes[i] + ";" + suffixes[i]);
      }

正确方式

ini 复制代码
    String[] prefixes;
    String[] suffixes;
    Map<Pair, Object> pairMap;
    // 获取数据
      for (int i = 0; i < prefixes.length; ++i) {
        pairMap.get(new Pair(prefixes[i], suffixes[i]));
      }

正确方式的性能是错误方式的3.7倍。

使用ThreadLocalRandom 替换 Random

Random 是java开发者非常熟悉的类,它的作用是用来生成随机数。它在功能上没有什么问题,唯一的问题是因为那部使用同步代码块,多个线程并发时,就会出现竞争、冲突问题,导致效率变慢。

ThreadLocalRandom 是JDK1.7中新推出的基于ThreadLocal的Radnom类,实现了每个线程拥有自己的Random类,避免了多线程时的冲突。

在JDK1.7版本以后,在任何场景都应该优先使用ThreadLocalRandom,它只有好处没有坏处。

使用debug日志时,避免不必要的函数调用

java中最有流行的日志框架当属Slf4j,其中就提供了debug方法来记录日志。debug 方法提供了占位符来避免在非debug日志等级时的字符串拼接。

logger.debug("Printing variable value: {}", variable);

但是在某些使用错误的场景中,就会带来意想不到的资源浪费。比如调用了json.toString();

ini 复制代码
JSONObject json = xxx;
logger.debug("Printing variable value: {}", json.toString());

这种使用方法会导致json.toString()会被调用,但是最后又不输出。使用logger.isDebugEnabled可以消除该问题。

ini 复制代码
JSONObject json = xxx;
if (logger.isDebugEnabled()) {
    logger.debug("Printing variable value: {}", json.toString());
}

停止使用JDK8

JDK8后续的LTS版本11中,包含了非常多的优化,比如String类的优化,GC的优化等。所有的java应用都大量使用String,在JDK8中,String比较大而且慢。在JDK8中,String使用char[]进行存储。

arduino 复制代码
private final char[] value;

JDK9以后变成了byte[];

arduino 复制代码
private final byte[] value;

一系列存储和编码的优化减少了String存储的大小和编码解码的速度。

总结

本文介绍了5种简单有效的java性能优化手段,以方便大家在工作写出更高效的程序

相关推荐
大波V56 分钟前
设计模式-参考的雷丰阳老师直播课
java·开发语言·设计模式
计算机-秋大田12 分钟前
基于微信小程序的平安驾校预约平台的设计与实现(源码+LW++远程调试+代码讲解等)
java·spring boot·微信小程序·小程序·vue·课程设计
《源码好优多》24 分钟前
基于Java Springboot旅游信息推荐系统
java·spring boot·旅游
岁月无声code26 分钟前
Spring Boot 牛刀小试 org.springframework.boot:spring-boot-maven-plugin:找不到类错误
java·spring boot·github
不爱学习的YY酱38 分钟前
【计网不挂科】计算机网络第二章< 物理层 >习题库(含答案)
java·数据库·计算机网络
_egg_38 分钟前
Unity音频导入设置
unity·性能优化·音频设置·音频优化
青云交44 分钟前
大数据新视界 -- 大数据大厂之 Impala 性能优化:新技术融合的无限可能(下)(12/30)
大数据·性能优化·impala·技术创新·新技术融合·电商案例·跨行业应用
南城花随雪。1 小时前
Spring框架之装饰者模式 (Decorator Pattern)
java·开发语言·装饰器模式
编程、小哥哥1 小时前
设计模式之装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)
java·设计模式·装饰器模式
hummhumm2 小时前
第 12 章 - Go语言 方法
java·开发语言·javascript·后端·python·sql·golang