在收集器中发现重复的密钥条目时。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));
在合并函数中,我想根据键来决定是否取消映射,或者继续并接受这些值。
当然,还有一个简单而琐碎的技巧——将密钥保存在“密钥映射器”函数中,并在“合并”函数中获取密钥。因此,代码可能如下所示(假设键是整数):
final AtomicInteger key = new AtomicInteger();
...collect( Collectors.toMap(
item -> { key.set(item.getKey()); return item.getKey(); }, // key mapper
item -> ..., // value mapper
(v1, v2) -> { log(key.get(), v1, v2); return v1; } // merge function
);
注意:这不利于并行处理。
当您忽略合并函数时,合并函数没有机会获得密钥,这与内置函数有相同的问题。
解决方案是使用不同的toMap
实现,它不依赖于Map。合并
:
public static <T, K, V> Collector<T, ?, Map<K,V>>
toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends V> valueMapper) {
return Collector.of(HashMap::new,
(m, t) -> {
K k = keyMapper.apply(t);
V v = Objects.requireNonNull(valueMapper.apply(t));
if(m.putIfAbsent(k, v) != null) throw duplicateKey(k, m.get(k), v);
},
(m1, m2) -> {
m2.forEach((k,v) -> {
if(m1.putIfAbsent(k, v)!=null) throw duplicateKey(k, m1.get(k), v);
});
return m1;
});
}
private static IllegalStateException duplicateKey(Object k, Object v1, Object v2) {
return new IllegalStateException("Duplicate key "+k+" (values "+v1+" and "+v2+')');
}
(这基本上就是Java
因此,在代码中只需重定向toMap
调用并省略merge函数:
String keyvalp = "test=one\ntest2=two\ntest2=three";
Map<String, String> map = Pattern.compile("\n")
.splitAsStream(keyvalp)
.map(entry -> entry.split("="))
.collect(toMap(split -> split[0], split -> split[1]));
(或ContainingClass.toMap
如果它既不在同一个类中,也不在静态导入中)
收集器支持与原始toMap
收集器类似的并行处理,尽管它不太可能从这里的并行处理中获益,即使有更多的元素要处理。
如果,如果我理解正确,您只想在基于实际键的合并函数中选择较旧或较新的值,您可以使用键谓词
这样做
public static <T, K, V> Collector<T, ?, Map<K,V>>
toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends V> valueMapper,
Predicate<? super K> useOlder) {
return Collector.of(HashMap::new,
(m, t) -> {
K k = keyMapper.apply(t);
m.merge(k, valueMapper.apply(t), (a,b) -> useOlder.test(k)? a: b);
},
(m1, m2) -> {
m2.forEach((k,v) -> m1.merge(k, v, (a,b) -> useOlder.test(k)? a: b));
return m1;
});
}
Map<String, String> map = Pattern.compile("\n")
.splitAsStream(keyvalp)
.map(entry -> entry.split("="))
.collect(toMap(split -> split[0], split -> split[1], key -> condition));
有几种方法可以自定义此收集器…
您需要使用自定义收集器或使用不同的方法。
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]));
编写一个自定义收集器是相当复杂的。你需要一个三消费者(键和两个值)是相似的,这不是在JDK中,这就是为什么我很确定没有内置函数使用。;)
使用for函数时,可以保存对象的位置,如(示例): 但是我不知道我怎么能得到这个位置,我怎么能知道它是否是最后一个使用地图功能的 有人能帮忙吗?
在Go中,有没有更简单/更好的方法从地图中获取一部分密钥? 目前,我正在遍历地图并将关键点复制到一个切片:
我在数据帧中有两个映射类型列。有没有一种方法可以通过使用.withColumn在spark Sql中合并这两个列来创建新的映射列?
本文向大家介绍iOS实现图片存在本地、再从本地获取图片的功能,包括了iOS实现图片存在本地、再从本地获取图片的功能的使用技巧和注意事项,需要的朋友参考一下 iOS实现图片存在本地、再从本地获取图片的功能,代码如下: 以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持呐喊教程!
问题内容: 问题 从地图中获取数据 资料格式 注意 如何从上述结果中获得以下值 1.Event_dtmReleaseDate 2.strID 3.Trans_strGuestList 我试过的 res.Map(“ Event_dtmReleaseDate”); 错误:res.Map未定义(类型map [string] interface {}没有字段或方法Map) res.Event_dtmRel
图形渲染 渲染系统,包括材质,光照,粒子等 UI系统 UI系统,包括与UI 相关的全部内容 动画系统 基于动画帧数据及骨骼顶点数据的通用动画及骨骼动画体系 音频 控制声音片段的播放暂停等 物理模拟 物理仿真模拟,主要包括刚体和碰撞等 脚本指南及事件系统 用于实现用户定义行为的脚本使用指南,包括事件的触发机制等 组件 用于为游戏对象添加不同功能的组件说明 资源 引擎使用到的各种不同资源介绍及整体资源