并行化双嵌套for循环

时间:2016-06-25 15:16:16

标签: java concurrency parallel-processing concurrenthashmap

我有一个非常大的列表,所以我需要加快整体速度,我正在尝试并行化这个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>

或者我使用这种方法做错了吗?

3 个答案:

答案 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);
         });