【问题标题】:Java how to iterate all values of HashMap in ParallelJava如何并行迭代HashMap的所有值
【发布时间】:2020-08-24 23:41:59
【问题描述】:

我有一个HashMap,其键类型为HashSet,值类型为ArrayList

将所有键值对插入到Map 后。我想迭代每个键及其值以进行进一步处理,而不仅仅是打印,它将用于键和值作为字符串参数传递的进一步过程。

所以我在想这是否可能,而不是在 Map 中一次迭代每个键值对,即等待第一次迭代结束以完成整个过程,然后才开始下一次迭代。相反,如果可以并行迭代所有键值而不必等待轮到它,那么整体结果会更快。迭代的顺序并不重要。它应该只并行读取所有键值对。

我尝试了 Stream API,但这只是并行打印所有迭代值,但在进一步的过程中,它并没有达到我的预期,也许我做错了什么,因为我不熟悉 Streams。如果使用可用的内置函数或类无法实现这一点,那么即使是第三方 Jars(Apache-commons)也可以。

这是我迄今为止尝试过的代码:

String jobId = "J1";
Map<Set<String>,List<String>> map_batch_result_details = new HashMap<Set<String>,List<String>>();
Set<String> hs_batchesId= new HashSet<String>();
List<String> list_resultId = new ArrayList<String>();

hs_batchesId.add("B1"); 
hs_batchesId.add("B2"); 
hs_batchesId.add("B3");

list_resultId.add("R1");
list_resultId.add("R2");
list_resultId.add("R3");


map_batch_result_details.put(hs_batchesId, list_resultId); 

map_batch_result_details.entrySet().stream().forEach(e -> {
System.out.format("key: %s, value: %s%n", e.getKey(), e.getValue());  // for printing results using stream without iterating each row sequentially instead iterates it parallely

 InputStream inputStream =  Connection.getQueryResultStream(jobId, e.getKey().toString(), e.getValue().toString());
/*
getQueryResultStream expects one batchId which is  <Key> of Map but it needs it in String so I am using toString
similarly third parameter expects one resultId which is <value> of Map again in String so toString
But Code fails as it is not passing 1 key and 1 value, rather it passes all key values at once in single call.
*/

});

输出

CALL: getQueryResultStream(jobId, e.getKey().toString(),e.getValue().toString());

**Actual values passed**
 getQueryResultStream(J1,[B1,B2,B3],[R1,R2,R3])

**Expected values**
getQueryResultStream(J1,B1,R1)
getQueryResultStream(J1,B2,R2)
getQueryResultStream(J1,B3,R3)

Expected value should execute in Parallel without having to wait for first iteration to get over. But not in one call which is happening in Actual values.

【问题讨论】:

  • 你试过map_batch_result_details.entrySet().parallelStream()而不是map_batch_result_details.entrySet().stream()吗?
  • @mexicomanni 即使使用 parallelStream(),它仍然在方法 getQueryResultStream(jobId, e.getKey().toString(), e.getValue().toString() 中传递 Map 的所有键和值与预期结果匹配。请查看我的帖子,我添加了实际和预期结果。
  • 你的HashMap中只有一个键值对,所以它不能并行处理任何东西。
  • @mexicomanni 我的错。感谢您的指出。

标签: java java-8 parallel-processing hashmap java-stream


【解决方案1】:

我有一个HashMap,其键类型为HashSet,值类型为ArrayList

这就是问题所在。无论键/值内部是什么,唯一的一个条目。此外,只要HashSet 是无序的,这种结构并不能保证"B1""R1" 绑定在一起。

我推荐使用不同结构的方式。您使用了 Map,其中只有一个条目同时具有键和值作为集合,这对于同时迭代是不切实际的。

我建议使用自定义或任何导入类 Pair&lt;T, R&gt;(使用 getter 方法说 firstsecond)或 Entry&lt;K, V&gt; 的列表,它们的工作方式相同:

List<Entry<String, String>> entries = new ArrayList<>();
entries.add(new SimpleEntry<>("B1", "R1"));
entries.add(new SimpleEntry<>("B2", "R2"));
entries.add(new SimpleEntry<>("B3", "R3"));

entries.parallelStream()
       .forEach(e -> System.out.format("key: %s, value: %s%n", e.getKey(), e.getValue()));

只要 Stream 是并行的,forEach 的输出就是无序的并且看起来是随机的。示例输出:

key: B2, value: R2
key: B1, value: R1
key: B3, value: R3

顺便说一句,您可能想要继续流式传输而不是使用forEach

entries.parallelStream()
       .map(e-> Connection.getQueryResultStream(jobId, e.getKey(), e.getValue()))
       ...

编辑:如果输入是 Map&lt;Set&lt;String&gt;, List&lt;String&gt;&gt; 并且您无法更改它,则使用以下 sn-p 将其转换为 List&lt;Entry&lt;String, String&gt;&gt;。唯一的希望是 SetLinkedHashSet 保持秩序,键和值之间的联系将保持原意:

map_batch_result_details.forEach((k, v) -> {
    Iterator<String> keysIterator = k.iterator();
    Iterator<String> valuesIterator = v.iterator();
    while (keysIterator.hasNext() && valuesIterator.hasNext()) {
        String key = keysIterator.next();
        String value = valuesIterator.next();
        entries.add(new SimpleEntry<>(key, value));
        }
    }
);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-23
    • 1970-01-01
    • 1970-01-01
    • 2015-09-19
    • 2011-03-21
    • 2014-12-07
    • 1970-01-01
    • 2011-03-16
    相关资源
    最近更新 更多