No Chill Bae
No Chill Bae

Reputation: 21

Merging values contained by key in a map (Java)

final Multimap<String, Map.Entry<Integer, Integer>>[] actionMap = new Multimap[]{null};
final boolean[] loaded = {false};

db.execute(connection -> {
    PreparedStatement statement = null;
    ResultSet resultSet = null;

    actionMap[0] = ArrayListMultimap.create();
    try {
        statement = connection.prepareStatement("Blah Blah...
        while (resultSet.next()) {
            final String name = ...

            actionMap[0].put(name, new AbstractMap.SimpleEntry<>(int1, int2));

I have a map where I use SimpleEntry to insert two integer values (int1, int2). On a duplicate key I want to merge values of what's already mapped. My idea is computeIfPresent but I have no idea of the BiFunctions since I'm using AbstractMap.SimpleEntry to enter the two values. Any help would be much appreciated.

Upvotes: 2

Views: 191

Answers (2)

Grzegorz Rożniecki
Grzegorz Rożniecki

Reputation: 27995

Based on input you gave (which could be more complete) it seems that you're trying to use wrong structure for your data. Assuming you want to merge value of the entry if both name and int1 exist, you should use Guava's Table instead. Let's consider this piece of code as an idea:

@Test
public void shouldMergeValues() throws SQLException {
    given(resultSet.getString("name"))
            .willReturn("name")
            .willReturn("name")
            .willReturn("name")
            .willReturn("name2");
    given(resultSet.getInt("key"))
            .willReturn(1)
            .willReturn(1)
            .willReturn(2)
            .willReturn(100);
    given(resultSet.getInt("value"))
            .willReturn(2)
            .willReturn(40)
            .willReturn(3)
            .willReturn(200);
    given(resultSet.next())
            .willReturn(true)
            .willReturn(true)
            .willReturn(true)
            .willReturn(true)
            .willReturn(false);

    Table<String, Integer, Integer> actionTable = HashBasedTable.create();

    while (resultSet.next()) {
        String name = resultSet.getString("name");
        int int1 = resultSet.getInt("key");
        int int2 = resultSet.getInt("value");
        if (actionTable.contains(name, int1)) {
            Integer oldInt2 = actionTable.get(name, int1);
            actionTable.put(name, int1, oldInt2 + int2); // in this example "+" is the "merge" function
        } else {
            actionTable.put(name, int1, int2);
        }
    }

    assertThat(actionTable) // {name={1=42, 2=3}, name2={100=200}}
            .containsCell("name", 1, 42)
            .containsCell("name", 2, 3)
            .containsCell("name2", 100, 200)
            .hasSize(3);
}

Given 4 rows: ("name", 1, 2), ("name", 1, 40), ("name", 2, 3) and ("name2", 100, 200) and example "merge" operation being addition, you'd get Table {name={1=42, 2=3}, name2={100=200}}. Please check if it fits your use case.

Upvotes: 0

queeg
queeg

Reputation: 9372

Before you put and overwrite, retrieve the existing value.

  • If you get null, there is no such value and you put as initially intended.
  • If you get something, merge your new data into something.

Upvotes: 1

Related Questions