java - Java如何并行迭代HashMap的所有值
问题描述
我有一个HashMap
with Key 的 typeHashSet
和 Value 的 type 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.
解决方案
我有一个
HashMap
with Key 的 typeHashSet
和 Value 的 typeArrayList
。
这就是问题。无论键/值内部是什么,唯一的一个条目。此外,只要是无序的,这种结构就不能保证"B1"
和绑定在一起。"R1"
HashSet
我推荐使用不同结构的方式。您使用 a Map
,其中只有一个条目同时具有键和值作为集合,这对于同时迭代是不切实际的。
我建议使用自定义或任何导入类的列表Pair<T, R>
(使用 getter 方法say first
and second
)或者Entry<K, V>
以相同的方式工作:
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<Set<String>, List<String>>
并且您无法更改它,则将其转换为List<Entry<String, String>>
使用以下代码段。唯一的希望是Set
维持LinkedHashSet
秩序,键和值之间的联系将保持原意:
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));
}
}
);
推荐阅读
- javascript - 未找到 Vue JS 模块(日期选择器)
- sap-cloud-sdk - 如何对 ODataQuery 和 ODataQueryBuilder 进行单元测试?
- javascript - 在刚刚退出全屏的视频元素(以及其他视频)上运行功能
- proxy - 我如何知道我是否在 NTLM 代理后面?
- wordpress - 根据产品类别更改 WooCommerce 缺货消息(产品页面)
- amazon-web-services - 在 Amazon Web Services S3 中保护存储桶和资源访问?
- ssl - nginx 和 bitnamis dockerized osclass 的 HTTP/HTTPS 重定向问题
- java - 无法创建自定义 BOM。项目构建失败并出现不可解析的导入 POM:找不到工件
- mysql - QMSQL:不能将不兼容的 Qt 库(版本 0x50b03)与此库(版本 0x50c05)混合
- reactjs - 在 @formatjs/intl-relativetimeformat/dist/locale-data/ 中哪里可以找到美国的语言环境