collections - Java8通过值中包含的键创建映射分组
问题描述
我有以下两个字符串列表:
{APPLE, ORANGE, BANANA} //call it keyList
{APPLE123, ORANGEXXX, 1APPLE, APPLEEEE} //call it valueList
所需的输出是HashMap<String, List<String>>
这样的:
<APPLE, {APPLE123, 1APPLE, APPLEEEE}>
<ORANGE, {ORANGEXXX}>
<BANANA, {}> //also <key, null> is accepted
我已经实施了这个解决方案(它有效)
HashMap<String, List<String>> myMap = new HashMap<>();
keyList.forEach(key -> {
List<String> values = valueList.stream()
.filter(value -> value.contains(key))
.collect(Collectors.toList());
myMap.put(key, values);
});
假设一个值仅与一个键相关(它是我的域的约束),就性能和/或代码清理而言,这是 java8 中的最佳解决方案吗?它可以以某种方式进行调整吗?
解决方案
如果您可以安全地假设每个值都与一个键相关联,并且只有一个键,那么您可以进入以下方向:
Pattern p = Pattern.compile(String.join("|", keyList));
Map<String, List<String>> map = valueList.stream()
.collect(Collectors.groupingBy(s -> {
Matcher m = p.matcher(s);
if(!m.find()) throw new AssertionError();
return m.group();
}));
map.forEach((k,v) -> System.out.println(k+": "+v));
如果键可能包含可能被误解为正则表达式结构的特殊字符,您可以将准备代码更改为
Pattern p = Pattern.compile(
keyList.stream().map(Pattern::quote).collect(Collectors.joining("|")));
该collect
操作只为现有值创建组。如果您真的需要所有键都存在,您可以使用
Map<String, List<String>> map = valueList.stream()
.collect(Collectors.groupingBy(s -> {
Matcher m = p.matcher(s);
if(!m.find()) throw new AssertionError();
return m.group();
},
HashMap::new, // ensure mutable map
Collectors.toList()
));
keyList.forEach(key -> map.putIfAbsent(key, Collections.emptyList()));
或者
Pattern p = Pattern.compile(
keyList.stream().map(Pattern::quote)
.collect(Collectors.joining("|", ".*(", ").*")));
Map<String, List<String>> map = valueList.stream()
.map(p::matcher)
.filter(Matcher::matches)
.collect(Collectors.groupingBy(m -> m.group(1),
HashMap::new, // ensure mutable map
Collectors.mapping(Matcher::group, Collectors.toList())
));
keyList.forEach(key -> map.putIfAbsent(key, Collections.emptyList()));
推荐阅读
- python - 如何从 Pandas 的数百列中删除丢失的内容?
- setuptools - 在 cli 程序中访问已安装的非 python 文件?
- javascript - 如何在启动时将持久会话初始化为护照/会话文件存储?
- cmake - Cmake 在 Windows 上找不到 wxWidgets
- c++ - 程序似乎正在接受文件输入但不打印信息
- javascript - 由于内联 JavaScript 函数调用不推荐使用 event。除了 addEventListener 之外,还有哪些替代方案?
- excel - xls 到新文件夹中的 xlsx 已完成但有错误消息
- vue.js - vue 可拖动,未调用添加的方法
- c - 需要帮助在 C 中处理文件,如何一次读取一个函数中的多行?
- c# - 如何设置字段
来自列表 使用 IEnumerable.Repeat