我有一个非常大的列表,所以我需要加快整体速度,我正在尝试并行化这个for循环:
public HashMap<String, String> getData()
{
//Both list are ArrayList<String>
HashMap<String, String> hashMap = new HashMap<>();
for (int w = 0; w < firstList.size(); w++) {
boolean once = false;
for (int j = 0; j < secondList.size(); j++) {
if (!once && secondList.get(j).var.startsWith(firstList.get(w).var.toLowerCase())) {
hashMap.put(firstList.get(w).var, secondList.get(j).var);
once = true;
}
}
}
return hashMap;
}
我找到了这个好的答案Parallelizing a for loop,但我并不真正理解如何将其应用到我的案例中,我应该为我Callable <output>
的{{1}}创建两个<K, V>
?
或者我使用这种方法做错了吗?
答案 0 :(得分:1)
我首先要用流重写它。这不仅会使代码可以并行化,而且还会使代码更具可读性。它还将避免原始代码中出现的所有重复,并确保以最佳方式迭代列表:
private static final class Entry {
private final String first;
private final String second;
// constructor, getters left as an exercise
}
public Map<String, String> getData() {
return firstList.stream()
.flatMap(firstListElement -> {
String lowercase = firstListElement.toLowerCase();
return secondList.stream()
.filter(secondListElement -> secondListElement.startsWith(lowercase))
.limit(1)
.map(secondListElement -> new Entry(firstListElement, secondListElement));
})
.collect(Collectors.toMap(Entry::getFirst, Entry::getSecond));
}
然后我将测量执行该操作所需的时间,并比较执行相同代码所需的时间,而不是firstList.parallelStream()
。
答案 1 :(得分:1)
问题不在于如何并行化循环。你使用的是错误的方法。
如果我理解正确,您希望列表1的每个元素都添加到列表2中以相同字符串开头的哈希映射1条目。
首先,当您找到匹配项并使用once
变量时,我不明白为什么您不会退出循环。
另外,为什么你需要once
变量,因为你可以检查hash1中是否已存在list1的单词?
无论如何,你应该使用TreeMap(检查NavigableMap接口)而不是检查密切匹配的hashmap。
另外,为什么在首先创建列表时你不能做这个逻辑呢?
也许你正试图优化错误的东西?
答案 2 :(得分:0)
这样的东西可以并行工作(在外部列表中)。但是只有281的列表,这可能不会增加太多价值。
在内部列表中,如果只找到匹配项,而不是第一次匹配项,那么该项工作也可以并行化,这将更有可能产生重大影响。
final ConcurrentMap<String, String> results = new ConcurrentHashMap<>();
firstList.stream()
.unordered()
.parallel()
.map(v1 -> v1.var)
.forEach(var -> {
final String lowerVar1 = var.toLowerCase();
secondList.stream()
.filter(v2 -> v2.var.startsWith(lowerVar1))
.findFirst()
.ifPresent(v2 -> results.put(var, v2.var);
});