2015-04-23 51 views
6

很像ImmutableList如何可以擴展爲這樣的ImmutableMap:擴展額外的或新的值

ImmutableList<Long> originalList = ImmutableList.of(1, 2, 3); 
ImmutableList<Long> extendedList = Iterables.concat(originalList, ImmutableList.of(4, 5)); 

如果我有一個現有的地圖,我怎麼能延長它(或替換值來創建一個新副本)?

ImmutableMap<String, Long> oldPrices = ImmutableMap.of("banana", 4, "apple", 7); 
ImmutableMap<String, Long> newPrices = … // Increase apple prices, leave others. 
             // => { "banana": 4, "apple": 9 } 

(讓我們不尋求有效的解決方案,因爲顯然that doesn't exist by design這個問題而尋求最慣用的解決方案。)

回答

11

你可以明確地創建一個生成器:

ImmutableMap<String, Long> oldPrices = ImmutableMap.of("banana", 4, "apple", 7); 
ImmutableMap<String, Long> newPrices = 
    new ImmutableMap.Builder() 
    .putAll(oldPrices) 
    .put("orange", 9) 
    .build(); 

編輯:
正如評論中指出的那樣,這將不允許覆蓋現有的值。這可以通過經歷不同Map的初始化器塊(例如,HashMap)來完成。這是什麼,但優雅,但它應該工作:

ImmutableMap<String, Long> oldPrices = ImmutableMap.of("banana", 4, "apple", 7); 
ImmutableMap<String, Long> newPrices = 
    new ImmutableMap.Builder() 
    .putAll(new HashMap<>() {{ 
     putAll(oldPrices); 
     put("orange", 9); // new value 
     put("apple", 12); // override an old value 
    }}) 
    .build(); 
+0

這裏的限制是不允許重複 - - 它不允許我增加蘋果的價格。 –

+0

@AndresJaanTack看到我編輯的答案。遠非優雅,但它應該做的伎倆。 – Mureinik

+4

請不要推薦「雙大括號初始化」。請參閱http://stackoverflow.com/a/9108655/95725和http://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/ – NamshubWriter

2

就在ImmutableMap複製到一個新的HashMap,新增的項目,並將其轉換爲一個新的ImmutableMap

ImmutableMap<String, Long> oldPrices = ImmutableMap.of("banana", 4, "apple", 7); 
Map<String, Long> copy = new HashMap<>(oldPrices); 
copy.put("orange", 9); // add a new entry 
copy.put("apple", 12); // replace the value of an existing entry 

ImmutableMap<String, Long> newPrices = ImmutableMap.copyOf(copy); 
0

嗯,我已經做到了這一點與但它並不完美:

public static <K,V> Map<K,V> update(final Map<K,V> map, final Map.Entry<K,V> replace) 
{ 
    return Stream.concat(
     Stream.of(replace), 
     map.entrySet().stream() 
      .filter(kv -> ! replace.getKey().equals(kv.getKey())) 
    .collect(Collectors.toMap(SimpleImmutableEntry::getKey, SimpleImmutableEntry::getValue)); 
} 

並且這隻會插入或更新單個條目。需要注意的是ImmutableMap &相關的收集器可以在被丟棄(這是我實際使用)

0

不是非常高性能的代碼,但下面會工作

private <K, V> ImmutableMap.Builder<K, V> update(final ImmutableMap.Builder<K, V> builder, final List<ImmutablePair<K, V>> replace) { 
    Set<K> keys = replace.stream().map(entry -> entry.getKey()).collect(toSet()); 
    Map<K, V> map = new HashMap<>(); 
    builder.build().forEach((key, val) -> { 
     if (!keys.contains(key)) { 
      map.put(key, val); 
     } 
    }); 
    ImmutableMap.Builder<K, V> newBuilder = ImmutableMap.builder(); 
    newBuilder.putAll(map); 
    replace.stream().forEach(kvEntry -> newBuilder.put(kvEntry.getKey(), kvEntry.getValue())); 
    return newBuilder; 
} 
+0

您能否解釋一下這段代碼的作用以及它如何解決這個問題? – Hexaholic

相關問題