Search code examples
javaguava

Copy an ImmutableMap with additional or new values


Much like how an ImmutableList could 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 could I extend 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 }

(Let's not seek an efficient solution, as apparently that doesn't exist by design. This question rather seeks the most idiomatic solution.)


Solution

  • You could 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 won't allow overriding existing values. This can be done by going through an initializer block of a different Map (e.g., a HashMap). It's anything 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();