共计 1239 个字符,预计需要花费 4 分钟才能阅读完成。
- 审慎看待 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…