我們?cè)跇I(yè)務(wù)上難免會(huì)遇到集合交集的處理,這邊總結(jié)了幾種方式比較,然后尋求最優(yōu)的方式。當(dāng)然如果集合數(shù)據(jù)比較少的情況下,選取的方式基本都能滿足需求,但是如果在數(shù)據(jù)量比較大的情況下呢?如果選取的方式不好,那么效率就會(huì)及其的低下。下面我們就集中方式展開分析。
ArrayList原生接口
retainAll(c)方式
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList<String>();
List<String> r = new ArrayList<>();
// 初始化數(shù)據(jù)
for (int i = 0; i < 30000; i++) {
list1.add("test" + i);
list2.add("test" + i * 3);
}
System.out.println("添加完成");
long t = System.currentTimeMillis();
list1.retainAll(list2);
System.out.println(System.currentTimeMillis() - t);
}
我們執(zhí)行上述代碼,我們一個(gè)集合3w的數(shù)據(jù),耗時(shí)時(shí)間基本都是在9s左右。
通過(guò)list遍歷contains判定方式
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList<String>();
List<String> r = new ArrayList<>();
for (int i = 0; i < 30000; i++) {
list1.add("test" + i);
list2.add("test" + i * 3);
}
System.out.println("添加完成");
long t = System.currentTimeMillis();
list1.stream().forEach(s->{
if(list2.contains(s)){
r.add(s);
}
});
System.out.println(System.currentTimeMillis() - t);
}
跟原生api的方式比較,效率差不多,通過(guò)代碼分析,原生api也是采用的是集合遍歷然后contains判定的。
List轉(zhuǎn)Map通過(guò)key來(lái)判定是否交叉
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList<String>();
List<String> r = new ArrayList<>();
for (int i = 0; i < 30000; i++) {
list1.add("test" + i);
list2.add("test" + i * 3);
}
System.out.println("添加完成");
long t = System.currentTimeMillis();
Map<String, String> map1 = list1.stream().collect(toMap(s -> s, Function.<String>identity()));
list2.stream().forEach(s -> {
String ss = map1.get(s);
if (ss != null) {
r.add(ss);
}
});
System.out.println(System.currentTimeMillis() - t);
}
執(zhí)行代碼跟上面兩種方式相比,效率是相當(dāng)?shù)母?,兩個(gè)數(shù)組都在3W級(jí)別的數(shù)量集,基本保持在100ms左右即可完成。