ImmutableMap extension with additional or new values

How and how ImmutableList can be extended as such:

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

If I have an existing map, how can I expand it (or create a new copy with replaced values)?

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

(Do not try to find an effective solution, as one that apparently does not exist by design . This question is rather looking for the most idiomatic solution.)

+6
source share
4 answers

You can explicitly create a builder:

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

EDIT:
As noted in the comments, this will not allow overriding existing values. This can be done by going through the initialization block of another Map (for example, a HashMap ). This is nothing but elegant, but it should work:

 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(); 
+11
source

Just copy ImmutableMap to the new HashMap , add elements and convert to the new 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); 
+2
source

Well, I did this with threads, but this is not ideal:

 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)); } 

and it only inserts or updates one record. Please note that ImmutableMap and its associated collector can be reset (which I used)

0
source

Not terribly perfect code, but below will work

 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
source

Source: https://habr.com/ru/post/985799/


All Articles