簡體   English   中英

有沒有更快的方法來使用Java查找不同的元素

[英]Is there faster way to find distinct elements using Java

我已經編寫了代碼,以在大量字符串中查找不同的元素。 代碼如下

HashMap<String, Integer> countMap = new HashMap<>();
String[] str={"aa","bb","cc","bb","aa","cc","aa","bb","cc","bb"};
for (String e : str) {
  if (!countMap.containsKey(e)) {
    countMap.put(e, 1);
  } 
}
Iterator it=countMap.keySet().iterator();
String[] db= new String[countMap.size()];
for(int i=0;i<countMap.size();i++){
  db[i]=(String)it.next();
  System.out.println(db[i]);
}

有沒有比這更快的代碼,因為我必須處理非常大的數組。

這不會(非常快),但是使用HashSet絕對會更優雅:

String[] str={"aa","bb","cc","bb","aa","cc","aa","bb","cc","bb"};
Set<String> distinct = new HashSet<>(Arrays.asList(str));
for(String s : distinct) {
    System.out.println(s);
}

您可以使用Java 8並行化所有工作:

String[] largeArray = null;

Set<String> distinctStrings = 
         Arrays.stream(largeArray).parallel()
        .collect(Collectors.toConcurrentMap((s) -> s, (s) -> s)).keySet();

這將一直擴展到ConcurrentMap的爭用成為問題為止。

您還可以在流上使用distinct函數:

Set<String> distinctStrings = Arrays.stream(largeArray).parallel()
    .distinct().collect(Collectors.toSet())

微基准

兩種方法都以1m GUID作為輸入運行(最壞的情況),進行了100次重復,測量了從中取出一組數據的時間。

Statistics stats = new Statistics();
for (int i = 0; i < 100; i++) {
  String[] largeArray = generate(1_000_000); // generates 1m UUIDs
  Stopwatch watch = Stopwatch.createStarted();

  // add the lambda here

  long time = watch.elapsed(TimeUnit.MILLISECONDS);
  System.out.println(distinctStrings.size());
  stats.add(time);
}

請注意 ,這不能衡量可伸縮性,您需要為該實驗改變輸入大小,以更准確地了解較大輸入的速度。

對於Java Stream Distinct解決方案:

[Min=358.0, Max=2236.0, Median=456.0, Mean=542.26, StandardDeviation=335.21174263441304]

對於ConcurrentMap解決方案:

[Min=85.0, Max=1020.0, Median=120.0, Mean=153.58, StandardDeviation=119.78281846742465]

順序使用HashSet

[Min=258.0, Max=1312.0, Median=281.0, Mean=307.39, StandardDeviation=125.63032237481526]

結果

您從並行化中獲得了相當不錯的加速, ConcurrentMap解決方案在輸入大小上的性能比順序版本好一些(對於更大的輸入大小/更多線程,可能有所不同)。

但是,並行Stream#distinct慢於順序版本。

哈希是正確的方法。 除了保留Map我們更喜歡Set 僅在內部使用地圖設置。

String[] str={"aa","bb","cc","bb","aa","cc","aa","bb","cc","bb"};
HashSet<String> uniques = new HashSet<String>();
for (String string : str) {
    uniques.add(string);
}

String[] result = new String[uniques.size()];
uniques.toArray(result);
System.out.println(Arrays.toString(result));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM