2014-11-14 63 views
1

現在,我將一些數值存儲爲HashBaseTable的值。當我想改變它的量,我需要寫類似:如何正確增加存儲在HashBaseTable中的值?

table.put("AS", "BS", table.get("AS", "BS") == null? 123: table.get("AS", "BS")+123); 

這在我的態度看起來相當混亂......是否有任何其他的方式來妥善處理?我的意思是沒有空檢查,離開地圖並再次放回去。 也許你可以建議任何其他數據類型而不是番石榴表?

謝謝!

回答

3

這大概去與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其中:

  1. 不番石榴存在,
  2. 將節省你的髒東西。

可能這個樣子,雖然命名會變得棘手和看跌期權的使用/從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。也許,如果有這樣的事情在番石榴內部在谷歌的一些番石榴開發能回答。)

1

我不確定你到底在問什麼。

但是你可以像這樣重構你的代碼。

Integer val = table.get("AS", "BS"); 
val = val == null ? 123 : (val + 123); 
table.put("AS", "BS", val); 
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) 

在這個模式中,你只能做一次查找和更新是因爲它不必再穿越地圖非常有效的。您並不是真正將緩存用作緩存,而只是一個加載映射。

只要你不需要用第一個鍵訪問地圖,我認爲這將工作得很好。

+0

這種方法也行,但我清理了你的代碼,我希望你不介意。如果它不應該被同時使用,我還會設置['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

+0

@Xaerxess我不介意。感謝修復和併發性建議。乾杯! – 2014-11-20 11:47:41

相關問題