使用Java在映射中自动创建缺失值的习惯用法

使用Java在映射中自动创建缺失值的习惯用法,java,collections,idioms,Java,Collections,Idioms,我经常使用映射将值存储在循环中,例如属于同一类/组的对象集/列表,或者我想要递增的原子整数。因此,我经常编写以下类型的代码(假设我没有在映射中存储null): /*示例#1——聚合*/ Map Map=newhashmap(); 对于(O O:oList){ K=o.getK(); 设置oSet=map.get(k); if(oSet==null){ oSet=新哈希集(o); map.put(k,oSet); }否则{ 添加(o); } } /*示例2——计数*/ Map Map=newhas

我经常使用映射将值存储在循环中,例如属于同一类/组的对象集/列表,或者我想要递增的原子整数。因此,我经常编写以下类型的代码(假设我没有在映射中存储null):

/*示例#1——聚合*/
Map Map=newhashmap();
对于(O O:oList){
K=o.getK();
设置oSet=map.get(k);
if(oSet==null){
oSet=新哈希集(o);
map.put(k,oSet);
}否则{
添加(o);
}
}
/*示例2——计数*/
Map Map=newhashmap();
对于(O O:oList){
K=o.getK();
原子整数i=map.get(k);
如果(i==null){
i=新的原子整数(1);
map.put(k,i);
}否则{
i、 增量();
}
}
我知道Apache公共集合
DefaultedMap
,它可以在工厂/模型对象丢失时动态创建值;但您依赖(另一个)外部库只是为了避免编写2/3行代码的麻烦(相当小)

是否有更简单的解决方案(特别是#2)?在这种情况下,您的开发伙伴会使用/推荐什么?是否有其他库提供这种“默认映射”?您是否编写自己的装饰地图?

谷歌也提供了这样的地图实现。 但我不会为了这么小的利益而使用图书馆。当你已经使用了这样一个库,你可以考虑使用地图。但总的来说,这只是我的观点,我不喜欢将库用于琐碎的事情

我觉得你问题中的例子很好。我也在用这个成语

在我看来,它就像Java WS的一部分

与执行的相同


因此,要回答您的问题,没有默认的实现,您必须滚动自己的实现或更好地使用其中一个实现。

在Java 8中,将方法
computeFabSent()
添加到
Map
接口:

default V computeIfAbsent(K键,函数
/* Example #1 -- aggregation */
Map<K, Set<O>> map = new HashMap<K, Set<O>>();
for (O o : oList) {
    K k = o.getK();
    Set<O> oSet = map.get(k);
    if (oSet == null) {
        oSet = new HashSet<O>(o);
        map.put(k, oSet);
    } else {
        oSet.add(o);
    }
}

/* Example #2 -- counting */
Map<K, AtomicInteger> map = new HashMap<K, AtomicInteger>();
for (O o : oList) {
    K k = o.getK();
    AtomicInteger i = map.get(k);
    if (i == null) {
        i = new AtomicInteger(1);
        map.put(k, i);
    } else {
        i.increment();
    }
}
map.computeIfAbsent(key, k -> new HashSet<V>()).add(v);
/* Example #1 -- aggregation */
Map<K, Set<O>> map = new HashMap<>();
oList.forEach(o -> map.computeIfAbsent(o.getK(), k -> new HashSet<>()).add(o));

/* Example #2 -- counting */
Map<K, AtomicInteger> map = new HashMap<>();
oList.forEach(o -> map.computeIfAbsent(o.getK(), k -> new AtomicInteger(0)).incrementAndGet());
/* Example #1 -- aggregation */
Map<K, Set<O>> map = oList.stream()
                          .collect(Collectors.groupingBy(O::getK, Collectors.toSet()));

/* Example #2 -- counting using a Long instead of an AtomicInteger */
Map<K, Long> map = oList.stream()
                        .map(O::getK)
                        .collect(Collectors.groupingBy(k -> k, Collectors.counting()));