现在,我将一些数值存储为HashBasedTable的值。当我想改变它的数量时,我需要写一些类似的东西:
table.put("AS", "BS", table.get("AS", "BS") == null? 123: table.get("AS", "BS")+123);
在我的感知中看起来相当混乱......有没有其他方法可以正确处理它?我的意思是没有空检查,离开地图并再次放回去。 也许你可以建议任何其他数据类型而不是Guava表?
谢谢!
答案 0 :(得分:3)
它大致采用Table
界面的方式,虽然我使用firstNonNull(T, T)
来避免调用get两次:
Table<String, String, Integer> table = HashBasedTable.create();
table.put("AS", "X", 2);
// with null check
table.put("AS", "BS", Objects.firstNonNull(table.get("AS", "BS"), 0) + 123);
System.out.println(table);
// prints: {AS={BS=123, X=2}}
另一方面,如果您真的不需要Table
界面和/或计数对您来说更重要(并且数字不是负数),请考虑使用Map<String, Multiset<String>
。获取多集时,空检查会更加痛苦,但添加元素会更容易(因为Multiset
的功能):
Map<String, Multiset<String>> mapWithMultiset = new HashMap<>();
// create new multiset to be put as value
HashMultiset<String> x = HashMultiset.create();
x.add("X", 2);
mapWithMultiset.put("AS", x);
// this feels dirty
if (!mapWithMultiset.containsKey("AS")) {
mapWithMultiset.put("AS", HashMultiset.<String>create());
}
mapWithMultiset.get("AS").add("BS", 123);
System.out.println(mapWithMultiset);
// prints: {AS=[BS x 123, X x 2]}
您似乎确实需要MultisetMultimap
又名BagMultimap
这样的内容:
可能看起来像这样,虽然命名会变得棘手,但Map
/ Collection
中使用put / add方法会让人感到困惑(显式免责声明:没有MultisetMultimap
):
MultisetMultimap<String, String> multisetMultimap = HashMultisetMultimap.create();
multisetMultimap.add("AS", "X", 2);
multisetMultimap.add("AS", "BS", 123);
System.out.println(mapWithMultiset);
// should print: {AS=[BS x 123, X x 2]}
(如果你对这个解决方案感兴趣,你应该使用new issue on Github。如果在谷歌内部的Guava中有一些类似的东西,也许一些Guava开发者可以回答。)< / p>
答案 1 :(得分:2)
我想到的是LoadingCache<StringPair, AtomicInteger>
。
关键是:
public final class StringPair {
private final String key1, key2;
// + constructor, hashCode, equals
}
我会这样创造......
LoadingCache<StringPair, AtomicInteger> cache = CacheBuilder.newBuilder()
.build(
new CacheLoader<StringPair, AtomicInteger>() {
public AtomicInteger load(StringPair key) {
return new AtomicInteger(0);
}
});
...然后
AtomicInteger value = cache.get(new StringPair("AB", "AB"));
value.addAndGet(123);
或
cache.get(new StringPair("AB", "AB")).addAndGet(123)
在此模式中,您只进行一次查找,并且更新非常高效,因为它不必再次遍历地图。您并没有真正将缓存用作缓存,而只是加载地图。
只要您不需要仅使用第一个键访问地图,我认为这样就可以了。
答案 2 :(得分:1)
我不确定你到底在问什么。
但你可以像这样重构你的代码。
Integer val = table.get("AS", "BS");
val = val == null ? 123 : (val + 123);
table.put("AS", "BS", val);