我编写了代码来查找大量字符串中的distinct元素。代码如下所示
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]);
}
是否有比这更快的代码,因为我必须处理非常大的数组。
答案 0 :(得分:5)
这不会(相当)更快,但使用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);
}
答案 1 :(得分:2)
您可以使用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
比顺序版慢。
答案 2 :(得分:0)
哈希是正确的方法。我们可以选择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));