リスト2の積集合は、おそらく学んだJavaはそれがシステムに付属している知っているretainAll()
が、それは大量のデータを受け、この方法では、ときに、2つの合計空き時間の使用がデータのいくつかの大規模な量を研究するために、非常に効率的ではありません収集方法の交差点。本論文グアバ、Java8 parallelStream並列ストリームの交差点のJDK自身、セット交差点の交差点の方法、及びビットマップ法と効率の交差点の交差点の両手法。
JDKには、メソッドが来ます
最も一般的に使用される方法の交差点、何の問題は、レベルの何千ものデータ量に達する何百二組と、効率が低い真剣ではない少量のデータは、下のはJDK実際にループのための2つですが、やりましたいくつかの対応する最適化ではなく、二重のforループはO(n ^ 2)、興味のある学生は、対応するソースコードを読むことができます。
グアバ収集ツール
グアバは便利な方法、の交点のための方法がたくさん含まれているGoogleのうち、のようなツールであるSets.intersection(list, list2)
、非常に効率的なダウン実際のテストを。
パラレルフローJava8
parallelStream()
借用フォーク/参加の枠組みJava7、交差点を模索するマルチスレッドパーティションのアイデアの使用
フィンガービス
二つのポインタ製二重ポインタ方法も知らファスナー方法、二組が最初にソートされ、次に借り思考ウェイマージソートは、2つのマーク内にセットし、その後、最終的な結果を与えるために、スライドの大きさを比較しています。
ビットマップ方式
操作続く2にデータを、ビットマップ、最終的な結果は、時間法のための空間に属し、ビットマップ大量のデータ処理に多くの不思議な考え方があります。
次の特定のコードの実装を貼り付けます。
package com.test.spring.learn.retainall;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.StringUtils;
import java.io.*;
import java.util.*;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toList;
/**
* Created by GeekBoy on 2020/1/4.
*/
public class RetainAllTest {
public static void main(String[] args) {
retainAllByGuava();
retainAllByBitSet();
retainAllByTwoPoint();
retainAllByStream();
retainAllByJDK();
}
/**
* 用JDK方法求交集
*/
private static void retainAllByJDK() {
List<Integer> txtList = getIntegerList("e:\\a.txt");
List<Integer> txtList2 = getIntegerList("e:\\b.txt");
long begin = System.currentTimeMillis();
txtList.retainAll(txtList2);
long end = System.currentTimeMillis();
System.out.println("JDK方法耗时:" + (end - begin));
System.out.println("交集的个数为:" + txtList.size());
}
/**
* 利用guava集合求交集
*/
private static void retainAllByGuava() {
List<Integer> txtList = getIntegerList("e:\\a.txt");
List<Integer> txtList2 = getIntegerList("e:\\b.txt");
long begin = System.currentTimeMillis();
Set<Integer> list = new HashSet<>(txtList);
Set<Integer> list2 = new HashSet<>(txtList2);
Sets.SetView<Integer> intersection = Sets.intersection(list, list2);
long end = System.currentTimeMillis();
System.out.println("guava方法耗时:" + (end - begin));
System.out.println("交集的个数为:" + intersection.size());
}
/**
* java8 stream流求交集,实质上底层是用的多线程fork/join框架
*/
private static void retainAllByStream() {
List<Integer> txtList = getIntegerList("e:\\a.txt");
List<Integer> txtList2 = getIntegerList("e:\\b.txt");
long begin = System.currentTimeMillis();
long count = txtList.parallelStream().
filter(item -> txtList2.contains(item)).count();
long end = System.currentTimeMillis();
System.out.println("stream流求交集方法耗时:" + (end - begin));
System.out.println("交集的个数为:" + count);
}
/**
* 双指针法求两个list的交集
*/
private static void retainAllByTwoPoint() {
List<Integer> txtList = getIntegerList("e:\\a.txt");
List<Integer> txtList2 = getIntegerList("e:\\b.txt");
long begin = System.currentTimeMillis();
Collections.sort(txtList);
Collections.sort(txtList2);
int count = 0;
int m = 0;
int n = 0;
int length = txtList.size() + txtList2.size();
for (int i = 0; i < length; i++) {
if (m < txtList.size() && n < txtList2.size()) {
if (txtList.get(m).equals(txtList2.get(n))) {
count++;
m++;
n++;
} else if (txtList.get(m).compareTo(txtList2.get(n)) > 0) {
n++;
} else {
m++;
}
} else if (m < txtList.size()) {
if (txtList.get(m).equals(txtList2.get(n - 1))) {
count++;
}
m++;
} else if (n < txtList2.size()) {
if (txtList.get(m - 1).equals(txtList2.get(n))) {
count++;
}
n++;
}
}
long end = System.currentTimeMillis();
System.out.println("双指针方法耗时:" + (end - begin));
System.out.println("交集的个数为:" + count);
}
/**
* 利用bitmap求两个list的交集
*/
private static void retainAllByBitSet() {
List<Integer> txtList = getIntegerList("e:\\a.txt");
List<Integer> txtList2 = getIntegerList("e:\\b.txt");
long begin = System.currentTimeMillis();
BitSet bitSet = new BitSet(Collections.max(txtList));
BitSet bitSet1 = new BitSet(Collections.max(txtList2));
for (int i = 0; i < txtList.size(); i++) {
bitSet.set(txtList.get(i));
}
for (int i = 0; i < txtList2.size(); i++) {
bitSet1.set(txtList2.get(i));
}
bitSet.and(bitSet1);
long end = System.currentTimeMillis();
System.out.println("bitSet方法耗时:" + (end - begin));
System.out.println("交集的个数为:" + bitSet.cardinality());
}
/**
* 从文件读取两个list<Integer>
*
* @param filePath
* @return
*/
private static List<Integer> getIntegerList(String filePath) {
InputStream inputStream = null;
InputStreamReader is = null;
BufferedReader br = null;
Set<Integer> txtList = new HashSet<>();
try {
File txtFile = new File(filePath);
if (txtFile.exists()) {
inputStream = new FileInputStream(txtFile);
is = new InputStreamReader(inputStream, "UTF-8");
br = new BufferedReader(is);
String str = null;
while ((str = br.readLine()) != null) {
if (StringUtils.isNotBlank(str)) {
txtList.add(Integer.valueOf(str));
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
if (is != null) {
is.close();
}
if (br != null) {
br.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return new ArrayList<>(txtList);
}
}
次のように最終的な結果は、唯一の結果は参照のため、厳密ではなく、一度に実行されます。
guava方法耗时:33
交集的个数为:151695
bitSet方法耗时:25
交集的个数为:151695
双指针方法耗时:63
交集的个数为:151695
stream流求交集方法耗时:28240
交集的个数为:151695
JDK方法耗时:91838
交集的个数为:151695
以上の結果を見ることができるから、bieSetが最速で、グアバ法第二に、JDKは最も遅いが付属しています。通常は、データの量が大幅に使用グアバない場合はツールを使用して、Googleのアルゴリズムは、まだ非常に強力であることを言わなければならないことができます。
参考リンク
https://blog.csdn.net/banpeng4018/article/details/101386744