学习笔记---java性能优化
Posted 歲月
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习笔记---java性能优化相关的知识,希望对你有一定的参考价值。
- 谨慎对待Java的循环遍历
Java中的列表遍历可比它看起来要麻烦多了。就以下面两段代码为例:
A:
private final List<Bar> _bars;
for(Bar bar : _bars) {
//Do important stuff
}
B:
private final List<Bar> _bars;
for(int i = 0; i < _bars.size(); i++) {
Bar bar = _bars.get(i);
}
代码A执行的时候会为这个抽象列表创建一个迭代器,而代码B就直接使用 get(i) 来获取元素,相对于代码A省去了迭代器的开销。
实际上这里还是需要一些权衡的。代码A使用了迭代器,保证了在获取元素的时候的时间复杂度是 O(1) (使用了 getNext() 和 hasNext() 方法),最终的时间复杂度为 O(n) 。但是对于代码B,循环里每次在调用 _bars.get(i) 的时候花费的时间复杂度为 O(n) (假设这个list为一个 LinkedList),那么最终代码B整个循环的时间复杂度就是 O(n^2) (但如果代码B里面的list是 ArrayList, 那 get(i) 方法的时间复杂度就是 O(1)了)。所以在决定使用哪一种遍历的方式的时候,我们需要考虑列表的底层实现,列表的平均长度以及所使用的内存。如果我们需要优化内存,再加上 ArrayList 在大多数情况下查找的时间复杂度为 O(1) ,可以选择代码B所使用的方法。
2.在初始化的时候预估集合的大小
从Java的这篇 文档我们可以了解到: “一个HashMap 实例有两个影响它性能的因素:初始大小和加载因子(load factor)。 当哈希表的大小达到初始大小和加载因子的乘积的时候,哈希表会进行 rehash操作。如果在一个HashMap 实例里面要存储多个映射关系时,我们需要设置足够大的初始化大小以便更有效地存储映射关系而不是让哈希表自动增长让后rehash,造成性能瓶颈。”
常常碰到需要遍历一个 ArrayList 并将这些元素保存到 HashMap 里面去,将这个 HashMap 初始化预期的大小可以避免再次哈希所带来的开销。初始化大小可以设置为输入的数组大小除以默认加载因子的结果值(这里取0.7):
优化前的代码:
HashMap<String,Foo> _map;
void addObjects(List<Foo> input)
{
_map = new HashMap<String, Foo>();
for(Foo f: input)
{
_map.put(f.getId(), f);
}
}
优化后的代码:
HashMap<String,Foo> _map;
void addObjects(List<Foo> input)
{
_map = new HashMap<String, Foo>((int)Math.ceil(input.size() / 0.7));
for(Foo f: input)
{
_map.put(f.getId(), f);
}
}
3.转载学习资料 https://blog.csdn.net/qq35960...
以上是关于学习笔记---java性能优化的主要内容,如果未能解决你的问题,请参考以下文章