mem*_*und 12 java java-8 collectors
当在期间找到重复的键条目时Collectors.toMap(),(o1, o2)调用合并功能.
问题:如何获取导致重复的密钥?
String keyvalp = "test=one\ntest2=two\ntest2=three";
Pattern.compile("\n")
.splitAsStream(keyval)
.map(entry -> entry.split("="))
.collect(Collectors.toMap(
split -> split[0],
split -> split[1],
(o1, o2) -> {
//TODO how to access the key that caused the duplicate? o1 and o2 are the values only
//split[0]; //which is the key, cannot be accessed here
},
HashMap::new));
Run Code Online (Sandbox Code Playgroud)
在合并函数内部,我想根据键来决定,如果我取消映射,或继续并接受这些值.
您需要使用自定义收集器或使用不同的方法.
Map<String, String> map = new Hashmap<>();
Pattern.compile("\n")
.splitAsStream(keyval)
.map(entry -> entry.split("="))
.forEach(arr -> map.merge(arr[0], arr[1], (o1, o2) -> /* use arr[0]));
Run Code Online (Sandbox Code Playgroud)
编写自定义收集器相当复杂.你需要一个TriConsumer(键和两个值)是类似的,它不在JDK中,这就是为什么我很确定没有内置函数使用.;)
当您省略合并函数时,合并函数没有机会获取密钥,这与内置函数有同样的问题。
\n\n解决方案是使用不同的toMap实现,它不依赖于Map.merge:
public static <T, K, V> Collector<T, ?, Map<K,V>>\n toMap(Function<? super T, ? extends K> keyMapper,\n Function<? super T, ? extends V> valueMapper) {\n return Collector.of(HashMap::new,\n (m, t) -> {\n K k = keyMapper.apply(t);\n V v = Objects.requireNonNull(valueMapper.apply(t));\n if(m.putIfAbsent(k, v) != null) throw duplicateKey(k, m.get(k), v);\n },\n (m1, m2) -> {\n m2.forEach((k,v) -> {\n if(m1.putIfAbsent(k, v)!=null) throw duplicateKey(k, m1.get(k), v);\n });\n return m1;\n });\n}\nprivate static IllegalStateException duplicateKey(Object k, Object v1, Object v2) {\n return new IllegalStateException("Duplicate key "+k+" (values "+v1+" and "+v2+\')\');\n}\nRun Code Online (Sandbox Code Playgroud)\n\n(这基本上就是toMap没有合并功能的 Java\xc2\xa09\xe2\x80\x99s 实现的作用)
因此,您在代码中需要做的就是重定向调用toMap并省略合并函数:
String keyvalp = "test=one\\ntest2=two\\ntest2=three";\n\nMap<String, String> map = Pattern.compile("\\n")\n .splitAsStream(keyvalp)\n .map(entry -> entry.split("="))\n .collect(toMap(split -> split[0], split -> split[1]));\nRun Code Online (Sandbox Code Playgroud)\n\n(或者ContainingClass.toMap如果它既不在同一类中也不在静态导入中)<\\sup>
该收集器像原始toMap收集器一样支持并行处理,尽管它\xe2\x80\x99不太可能从此处的并行处理中受益,即使有更多元素要处理。
如果,如果我理解正确的话,您只想在基于实际键的合并函数中选择较旧或较新的值,则可以使用Predicate这样的键来完成
public static <T, K, V> Collector<T, ?, Map<K,V>>\n toMap(Function<? super T, ? extends K> keyMapper,\n Function<? super T, ? extends V> valueMapper,\n Predicate<? super K> useOlder) {\n return Collector.of(HashMap::new,\n (m, t) -> {\n K k = keyMapper.apply(t);\n m.merge(k, valueMapper.apply(t), (a,b) -> useOlder.test(k)? a: b);\n },\n (m1, m2) -> {\n m2.forEach((k,v) -> m1.merge(k, v, (a,b) -> useOlder.test(k)? a: b));\n return m1;\n });\n}\nRun Code Online (Sandbox Code Playgroud)\n\n\n\nMap<String, String> map = Pattern.compile("\\n")\n .splitAsStream(keyvalp)\n .map(entry -> entry.split("="))\n .collect(toMap(split -> split[0], split -> split[1], key -> condition));\nRun Code Online (Sandbox Code Playgroud)\n\n有几种方法可以自定义这个收集器\xe2\x80\xa6
\n| 归档时间: |
|
| 查看次数: |
3765 次 |
| 最近记录: |