現在,我將一些數值存儲爲HashBaseTable的值。當我想改變它的量,我需要寫類似:如何正確增加存儲在HashBaseTable中的值?
table.put("AS", "BS", table.get("AS", "BS") == null? 123: table.get("AS", "BS")+123);
這在我的態度看起來相當混亂......是否有任何其他的方式來妥善處理?我的意思是沒有空檢查,離開地圖並再次放回去。 也許你可以建議任何其他數據類型而不是番石榴表?
謝謝!
現在,我將一些數值存儲爲HashBaseTable的值。當我想改變它的量,我需要寫類似:如何正確增加存儲在HashBaseTable中的值?
table.put("AS", "BS", table.get("AS", "BS") == null? 123: table.get("AS", "BS")+123);
這在我的態度看起來相當混亂......是否有任何其他的方式來妥善處理?我的意思是沒有空檢查,離開地圖並再次放回去。 也許你可以建議任何其他數據類型而不是番石榴表?
謝謝!
這大概去與Table
接口的方式,但我會用firstNonNull(T, T)
避免調用得到兩倍:
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
添加方法會有點難以理解(明確聲明:有沒有這樣的事情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。也許,如果有這樣的事情在番石榴內部在谷歌的一些番石榴開發能回答。)
我不確定你到底在問什麼。
但是你可以像這樣重構你的代碼。
Integer val = table.get("AS", "BS");
val = val == null ? 123 : (val + 123);
table.put("AS", "BS", val);
我想到的是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)
在這個模式中,你只能做一次查找和更新是因爲它不必再穿越地圖非常有效的。您並不是真正將緩存用作緩存,而只是一個加載映射。
只要你不需要用第一個鍵訪問地圖,我認爲這將工作得很好。
這種方法也行,但我清理了你的代碼,我希望你不介意。如果它不應該被同時使用,我還會設置['CacheBuilder#concurrencyLevel(int)'](http://docs.guava-libraries.googlecode.com/git-history/v18.0/javadoc /com/google/common/cache/CacheBuilder.html#concurrencyLevel(int))爲1。 – Xaerxess 2014-11-18 08:06:16
@Xaerxess我不介意。感謝修復和併發性建議。乾杯! – 2014-11-20 11:47:41