一对多Map
我们知道传统的map,支持一对一的映射,如果要使用一对多,则可以定义成Map<Object,List<Object>>方式。
一般写法如下:
public static <K, V> void addMapList(K key, V value, Map<K, List<V>> map) {
List<V> valueList = map.get(key);
if (null == valueList) {
valueList = new ArrayList<>();
map.put(key, valueList);
}
valueList.add(value);
}
Multimap实现
Guava提供针对一对提供了更为方便的实现:
private ListMultimap<Class<?>, Object> mapNormal = ArrayListMultimap.create();
项目中采用也是上述方式,同时也确认了该实现的map是线程不安全的,所以增加了线程安全的包装处理,如下:
private ListMultimap<Class<?>, Object> mapNormal = ArrayListMultimap.create();
public Multimap<Class<?>, Object> stage = Multimaps.synchronizedMultimap(mapNormal);
诡异的丢数据
原以为有个synchronized的封装,不会存在并发问题,但后面仍然出现了诡异的丢数据bug,经反复定位后,发现处理逻辑中仍有线程不安全地方。具体案例如下(与代码规范有关):
private void handleWithError() {
map.asMap().entrySet()
.stream()
.map(k -> CompletableFuture.runAsync(
() -