金麟岂是池中物,一遇风云便化龙
技术生活
遍历Map<K, Collection<V>>的正确方法
Mar 24th
对于value为集合的map,一般直觉上我们可能会选用下面的方式遍历map中所有collection的所有对象:
1 2 3 4 5 | for(K key:map.keySet()){ for(V value:map.get(key)){ // do sth. } } |
实际上,这种方式在第二行上会因为对哈希表的查询浪费效率,正确的做法应该这样:
for(List<V> list:map.values()){ for(V o:list){ // do sth. } }
或者
for(Map.Entry<K,List<V>> entry:map.entrySet()){ for(V o:entry.getValue()){ // do sth. } }
如何让Netbeans以英文模式启动
Mar 16th
不得不承认,Sun在Java及其周边产品的本地化上下了很大的功夫,比如中文版的Javadoc,NB,GlassFish……但是,Sun不得不承认的是,这些本地化尤其是后两个做得太TM狗屎了。每次新装Sun为我们“精心准备”的130+ MB的“中文版”的、菜单参杂着中英文的NB时我就想骂街。之前自己摸索了一种方法把版本强制转换为英文,就是到NB的安装目录下,搜索*zh_CN.jar,能搜到一堆的L10N的jar包,然后全部删了就好了。后来小权提供了一个更方便的招:打开NB安装目录下etc/netbeans.conf文件,在“netbeans_default_options=”最后(引号内)加上
--locale en_US重启NB,整个世界都清净了~~
慎用LinkedXxxx集合
Mar 5th
这两天发现项目中有个模块有内存泄露,512 MB的堆内存大概在5个小时左右被耗尽。通过NB的profiler跟踪可以看到如下结果:
java.util.concurrent.LinkedBlockingQueue.Node对象尽然占了一多半。在实时profile中发现即使限定了list的capacity并且在不断调用take方法(相当于remove)时,Node的alive object数量仍在不断增长(照理说在某个时间节点后alive object数量应该增长得很缓慢,因为take的Node对象会被GC)。将LinkedBlockingQueue换成ArrayBlockingQueue后问题解决。继而发现LinkedList有同样的问题,于是得出结论:
- LinkedXxxx集合的remove、take,甚至clear方法不会导致被挪出队列的node马上被标记为可GC,可能会经过一个很长的时间(generation数量相当大)
- 由1推测LinkedXxxx的实现可能有内存泄露,或者JVM的GC算法可能有缺陷
- 由1、2得出经验:在集合内容需要做频繁替换(不断add/remove或者put/take)且程序运行时间很长的情况下最好不要使用LinkedXxxx,应该用ArrayXxxx替代并且指定capacity
补:感谢blader的补充,这个问题果然是个bug:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6460501








