例如List<V> aa 和List<V> bb,要求两个列表的交集
数据量上百万的时候retainAll()超级超级慢,没有解决办法,因为reatainAll的原理就是遍历外层列表比如aa(aa通常是数量较少的列表),再在循环里判断bb是否包含当前正遍历到的元素aa.get(i),而判断是否包含时contains方法又是一个很笨重的办法,它的原理是去获取元素的下标indexOf,即在列表中依次遍历匹配目标元素直至找到相同的元素...太慢了...慢的我失去耐心等不到结果...
但是可以切换思路,换个方法解决求交集的问题。
使用唯一标识作为Map的key存储两个列表元素,将求List<V> aa 和List<V> bb 的交集问题,改成求Map<K,V>的交集,遍历Map.Entry,判断if(bb.containsKey(entry.getKey())){},如下
Map<String,String> aa = new HashMap<>();
Map<String,String> bb = new HashMap<>();
for(int i=0; i<1000000;i++){
aa.put("stringggg"+i,"stringggg"+i);
}
for(int j=0; j<1000000;j++){
bb.put("bbstringggg"+j,"bbstringggg"+j);
}
for(int k=0; k<1000000;k++){
bb.put("stringggg"+k,"stringggg"+k);
}
System.out.println(System.currentTimeMillis()+" start retainAll by Map...");
List<String> cc = new ArrayList<>();
for(Map.Entry<String,String> ee:aa.entrySet()){
if(bb.containsKey(ee.getKey())){
cc.add(ee.getKey());
}
}
System.out.println(System.currentTimeMillis()+" end retainAll by Map..."+ cc.size());
输出:
183ms,感动
原因就是HashMap的containsKey方法,它使用hashcode查找集合,大大减少元素比较次数,类比ListArrayList的两层循环,相当于省去了内层循环,提高查找效率!这样使用HashMap求交集会快速许多。