java.util.Map#merge ( )源码实例Demo

下面列出了java.util.Map#merge ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

源代码1 项目: kork   文件: MapUtils.java
/**
 * Returns a new map that is the result of deeply merging original and overrides.
 *
 * <p>Each key in original is merged with the corresponding key in overrides as follows: - an
 * explicitly null entry in overrides removes a key in original - a map in original is merged with
 * a map from overrides (via call to merge) - a non map in overrides results in an
 * IllegalStateException - a collection in original is replaced with a collection in overrides - a
 * non collection in overrides results in an IllegalStateException - the value is taken from
 * overrides
 *
 * <p>Each remaining key in overrides is then added to the resulting map.
 *
 * @param original the original Map
 * @param override the Map to override/merge into original
 * @return a new Map containing the merge of original and overrides (never null)
 * @throws IllegalStateException if incompatible types exist between original and overrides
 */
@Nonnull
public static Map<String, Object> merge(
    @Nonnull Map<String, Object> original, @Nonnull Map<String, Object> override) {
  final Set<String> remainingKeys = new LinkedHashSet<>(override.keySet());
  final Map<String, Object> result = new LinkedHashMap<>();
  for (Map.Entry<String, Object> entry : original.entrySet()) {
    final String key = entry.getKey();
    result.put(key, entry.getValue());
    if (override.containsKey(key)) {
      final Object value = override.get(key);
      if (value == null) {
        result.remove(key);
      } else {
        result.merge(key, value, MapUtils::mergeObject);
      }
    }
    remainingKeys.remove(key);
  }
  for (String newKey : remainingKeys) {
    result.put(newKey, override.get(newKey));
  }

  return result;
}
 
@Override
public void updateCount(Tuple4<Long, Long, Long, IntType> value, Map<Long, Integer> windowCounts) {
	// verify the contents of that window, Tuple4.f1 and .f2 are the window start/end
	// the sum should be "sum (start .. end-1)"

	int expectedSum = 0;
	// we shorten the range if it goes beyond elementsPerKey, because those are "incomplete" sliding windows
	long countUntil = Math.min(value.f2, elementsPerKey);
	for (long i = value.f1; i < countUntil; i++) {
		// only sum up positive vals, to filter out the negative start of the
		// first sliding windows
		if (i > 0) {
			expectedSum += i;
		}
	}

	assertEquals("Window start: " + value.f1 + " end: " + value.f2, expectedSum, value.f3.value);

	windowCounts.merge(value.f0, 1, (val, increment) -> val + increment);
}
 
@Override
public void updateCount(Tuple4<Long, Long, Long, IntType> value, Map<Long, Integer> windowCounts) {
	// verify the contents of that window, Tuple4.f1 and .f2 are the window start/end
	// the sum should be "sum (start .. end-1)"

	int expectedSum = 0;
	// we shorten the range if it goes beyond elementsPerKey, because those are "incomplete" sliding windows
	long countUntil = Math.min(value.f2, elementsPerKey);
	for (long i = value.f1; i < countUntil; i++) {
		// only sum up positive vals, to filter out the negative start of the
		// first sliding windows
		if (i > 0) {
			expectedSum += i;
		}
	}

	assertEquals("Window start: " + value.f1 + " end: " + value.f2, expectedSum, value.f3.value);

	windowCounts.merge(value.f0, 1, (val, increment) -> val + increment);
}
 
源代码4 项目: caffeine   文件: ReferenceTest.java
@Test(dataProvider = "caches", expectedExceptions = DeleteException.class)
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
    implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
    expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
    weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
    compute = Compute.SYNC, removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL)
public void merge_writerFails(Map<Integer, Integer> map, CacheContext context) {
  Integer key = context.firstKey();
  try {
    context.clear();
    GcFinalization.awaitFullGc();
    map.merge(key, context.absentValue(), (k, v) -> v);
  } finally {
    context.disableRejectingCacheWriter();
    assertThat(map.isEmpty(), is(false));
  }
}
 
源代码5 项目: caffeine   文件: ExpirationTest.java
@Test(dataProvider = "caches")
@CacheSpec(population = Population.FULL, expiryTime = Expire.ONE_MINUTE,
    mustExpireWithAnyOf = { AFTER_WRITE, VARIABLE },
    expiry = { CacheExpiry.DISABLED, CacheExpiry.WRITE },
    expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE})
public void merge_writeTime(Map<Integer, Integer> map, CacheContext context) {
  Integer key = context.firstKey();
  Integer value = context.absentValue();

  map.merge(key, value, (oldValue, v) -> {
    context.ticker().advance(5, TimeUnit.MINUTES);
    return value;
  });
  context.cleanUp();
  assertThat(map.size(), is(1));
  assertThat(map.containsKey(key), is(true));
}
 
源代码6 项目: javacore   文件: Maps1.java
public static void main(String[] args) {
    Map<Integer, String> map = new HashMap<>();

    for (int i = 0; i < 10; i++) {
        map.putIfAbsent(i, "val" + i);
    }

    map.forEach((id, val) -> System.out.println(val));

    map.computeIfPresent(3, (num, val) -> val + num);
    System.out.println(map.get(3)); // val33

    map.computeIfPresent(9, (num, val) -> null);
    System.out.println(map.containsKey(9)); // false

    map.computeIfAbsent(23, num -> "val" + num);
    System.out.println(map.containsKey(23)); // true

    map.computeIfAbsent(3, num -> "bam");
    System.out.println(map.get(3)); // val33

    System.out.println(map.getOrDefault(42, "not found")); // not found

    map.remove(3, "val3");
    System.out.println(map.get(3)); // val33

    map.remove(3, "val33");
    System.out.println(map.get(3)); // null

    map.merge(9, "val9", (value, newValue) -> value.concat(newValue));
    System.out.println(map.get(9)); // val9

    map.merge(9, "concat", (value, newValue) -> value.concat(newValue));
    System.out.println(map.get(9)); // val9concat
}
 
源代码7 项目: djl   文件: IntegrationTest.java
private boolean runTests(List<TestClass> tests) {
    Map<TestResult, Integer> totals = new ConcurrentHashMap<>();
    for (TestClass testClass : tests) {
        logger.info("Running test {} ...", testClass.getName());
        int testCount = testClass.getTestCount();

        try {
            if (!testClass.beforeClass()) {
                totals.merge(TestResult.FAILED, testCount, Integer::sum);
                continue;
            }

            for (int i = 0; i < testCount; ++i) {
                TestResult result = testClass.runTest(i);
                totals.merge(result, 1, Integer::sum);
            }
        } finally {
            testClass.afterClass();
        }
    }

    int totalFailed = totals.getOrDefault(TestResult.FAILED, 0);
    int totalPassed = totals.getOrDefault(TestResult.SUCCESS, 0);
    int totalSkipped = totals.getOrDefault(TestResult.SKIPPED, 0);
    int totalUnsupported = totals.getOrDefault(TestResult.UNSUPPORTED, 0);
    if (totalSkipped > 0) {
        logger.info("Skipped: {} tests", totalSkipped);
    }
    if (totalUnsupported > 0) {
        logger.info("Unsupported: {} tests", totalUnsupported);
    }
    if (totalFailed > 0) {
        logger.error("Failed {} out of {} tests", totalFailed, totalFailed + totalPassed);
    } else {
        logger.info("Passed all {} tests", totalPassed);
    }
    return totalFailed == 0;
}
 
源代码8 项目: caffeine   文件: AsMapTest.java
@CheckNoWriter
@Test(dataProvider = "caches")
@CacheSpec(population = { Population.SINGLETON, Population.PARTIAL, Population.FULL },
    removalListener = { Listener.DEFAULT, Listener.REJECTING })
public void merge_error(Map<Integer, Integer> map, CacheContext context) {
  try {
    map.merge(context.firstKey(), context.original().get(context.firstKey()),
        (oldValue, value) -> { throw new Error(); });
  } catch (Error e) {}
  assertThat(context, both(hasMissCount(0)).and(hasHitCount(0)));
  assertThat(context, both(hasLoadSuccessCount(0)).and(hasLoadFailureCount(1)));
  assertThat(map, is(equalTo(context.original())));
}
 
源代码9 项目: caffeine   文件: AsMapTest.java
@CheckNoWriter @CheckNoStats
@Test(dataProvider = "caches")
@CacheSpec(removalListener = { Listener.DEFAULT, Listener.REJECTING })
public void merge_absent(Map<Integer, Integer> map, CacheContext context) {
  Integer result = map.merge(context.absentKey(),
      context.absentValue(), (oldValue, value) -> value);
  assertThat(result, is(context.absentValue()));

  assertThat(map.get(context.absentKey()), is(context.absentValue()));
  assertThat(map.size(), is(1 + context.original().size()));
}
 
源代码10 项目: lucene-solr   文件: TestPointFields.java
/**
 * @param field the field to use for indexing and searching against
 * @param searchable set to true if searches against "field" should succeed, false if field is only stored and searches should always get numFound=0
 */
private void doTestFloatPointFieldExactQuery(final String field, final boolean searchable, final boolean testDouble) 
    throws Exception {
  int numValues = 10 * RANDOM_MULTIPLIER;
  Map<String,Integer> randCount = new HashMap<>(numValues);
  String[] rand = testDouble ? toStringArray(getRandomDoubles(numValues, false)) 
                             : toStringArray(getRandomFloats(numValues, false));
  for (int i = 0 ; i < numValues ; i++) {
    randCount.merge(rand[i], 1, (a, b) -> a + b); // count unique values
    assertU(adoc("id", String.valueOf(i), field, rand[i]));
  }
  assertU(commit());

  for (int i = 0 ; i < numValues ; i++) {
    assertQ(req("q", field + ":" + (rand[i].startsWith("-") ? "\\" : "") + rand[i],
        "fl", "id," + field), getTestString(searchable, randCount.get(rand[i])));
  }

  StringBuilder builder = new StringBuilder();
  for (String value : randCount.keySet()) {
    if (builder.length() != 0) {
      builder.append(" OR ");
    }
    if (value.startsWith("-")) {
      builder.append("\\"); // escape negative sign
    }
    builder.append(value);
  }
  assertQ(req("debug", "true", "q", field + ":(" + builder.toString() + ")"), getTestString(searchable, numValues));

  clearIndex();
  assertU(commit());
}
 
源代码11 项目: openjdk-jdk9   文件: InPlaceOpsCollisions.java
@Test(dataProvider = "hashMapsWithObjects")
void testMergeNonNull(String desc, Supplier<Map<IntKey, IntKey>> ms, IntKey val) {
    // remove a third of the keys
    // call merge() for all keys[]
    // all keys should be present: removed keys now -> EXTRA, other keys -> k-1
    Map<IntKey, IntKey> map = ms.get();
    IntKey[] keys = map.keySet().stream().sorted().toArray(IntKey[]::new);

    // Map to preceding key
    BiFunction<IntKey, IntKey, IntKey> mappingFunction
            = (k, v) -> keys[k.getValue() - 1];
    removeThirdKeys(map, keys);
    for (int i = 1; i < keys.length; i++) {
        IntKey retVal = map.merge(keys[i], val, mappingFunction);
        if (i % 3 != 2) { // key present, should be mapped to k-1
            assertEquals(retVal, keys[i - 1],
                    String.format("compute: retVal(%s[%d])", desc, i));
            assertEquals(keys[i - 1], map.get(keys[i]),
                    String.format("compute: get(%s[%d])", desc, i));
        } else { // odd: was removed, should be replaced with EXTRA
            assertEquals(retVal, val,
                    String.format("compute: retVal(%s[%d])", desc, i));
            assertEquals(val, map.get(keys[i]),
                    String.format("compute: get(%s[%d])", desc, i));
        }
        assertTrue(map.containsKey(keys[i]),
                String.format("compute: containsKey(%s[%d])", desc, i));
    }

    assertEquals(map.size(), keys.length,
            String.format("map expected size#1 m%d != k%d", map.size(), keys.length));
    assertTrue(map.containsValue(val),
            String.format("compute: containsValue(%s[%s])", desc, val));
    assertFalse(map.containsValue(null),
            String.format("compute: !containsValue(%s,[null])", desc));
}
 
源代码12 项目: kafka-graphs   文件: PregelComputation.java
private Callback callback(int superstep, K readOnlyKey, K vertex, List<Message> messages) {
    return (metadata, error) -> {
        if (error == null) {
            try {
                // Activate partition for next step
                int p = vertexToPartition(vertex, serialized.keySerde().serializer(), numPartitions);
                log.debug("Step {}, adding partition {} for vertex {}", superstep, p, vertex);
                ZKUtils.addChild(curator, applicationId, new PregelState(State.RUNNING, superstep + 1, Stage.SEND), childPath(p));

                Map<Integer, Long> endOffsets = lastWrittenOffsets.computeIfAbsent(superstep, k -> new ConcurrentHashMap<>());
                endOffsets.merge(metadata.partition(), metadata.offset(), Math::max);
            } catch (Exception e) {
                throw toRuntimeException(e);
            }
        } else if (error instanceof RecordTooLargeException && messages.size() > 1) {
            log.warn("Record too large, retrying with smaller messages");
            for (Message message : messages) {
                List<Message> singleton = Collections.singletonList(message);
                Tuple3<Integer, K, List<Message>> tuple = new Tuple3<>(superstep + 1, readOnlyKey, singleton);
                ProducerRecord<K, Tuple3<Integer, K, List<Message>>> record =
                    new ProducerRecord<>(workSetTopic, vertex, tuple);
                producer.send(record, callback(superstep, readOnlyKey, vertex, singleton));
            }
        } else {
            log.error("Failed to send record to {}: {}", workSetTopic, error);
        }
    };
}
 
源代码13 项目: caffeine   文件: AsMapTest.java
@CheckNoWriter @CheckNoStats
@CacheSpec(removalListener = { Listener.DEFAULT, Listener.REJECTING })
@Test(dataProvider = "caches", expectedExceptions = NullPointerException.class)
public void merge_nullMappingFunction(Map<Integer, Integer> map, CacheContext context) {
  map.merge(1, 1, null);
}
 
源代码14 项目: fdb-record-layer   文件: Comparisons.java
@Nullable
private static Boolean compareTextContainsAllWithin(@Nonnull Iterator<? extends CharSequence> valueIterator, @Nonnull List<String> comparand, int maxDistance) {
    final Set<String> comparandSet = getComparandSet(comparand);
    if (comparandSet.isEmpty()) {
        return null;
    }
    if (comparandSet.size() == 1) {
        return compareTextContainsSingle(valueIterator, comparandSet.iterator().next());
    }

    // Maintain a queue of the last maxDistance tokens. Then keep a histogram
    // of the number of times we've seen each token we care about in that
    // range. Then we know we've seen all of them when the size of the
    // map is equal to the size of the set.
    final Map<String, Integer> seenMap = new HashMap<>(comparandSet.size());
    final Queue<String> lastTokensQueue = new ArrayDeque<>(maxDistance);
    while (valueIterator.hasNext()) {
        final String nextToken = valueIterator.next().toString();
        if (!nextToken.isEmpty() && comparandSet.contains(nextToken)) {
            // We have a match. Add one (or set the count to 1) for the
            // matched token.
            seenMap.merge(nextToken, 1, Integer::sum);
            if (seenMap.size() == comparandSet.size()) {
                return Boolean.TRUE;
            }
        }

        // Update the histogram and the queue, removing the old
        // queue entry and then adding this next token if we
        // have hit the end of the road.
        if (lastTokensQueue.size() == maxDistance) {
            final String lastToken = lastTokensQueue.poll();
            seenMap.computeIfPresent(lastToken, (ignore, currentCount) -> {
                if (currentCount > 1) {
                    return currentCount - 1;
                } else {
                    // Gone to zero. Remove from map.
                    return null;
                }
            });
        }
        lastTokensQueue.offer(nextToken);
    }

    return Boolean.FALSE;
}
 
源代码15 项目: jdk8u_jdk   文件: Defaults.java
@Test(dataProvider = "MergeCases")
private void testMerge(String description, Map<IntegerEnum, String> map, Merging.Value oldValue, Merging.Value newValue, Merging.Merger merger, Merging.Value put, Merging.Value result) {
        // add and check initial conditions.
        switch(oldValue) {
            case ABSENT :
                map.remove(EXTRA_KEY);
                assertFalse(map.containsKey(EXTRA_KEY), "key not absent");
                break;
            case NULL :
                map.put(EXTRA_KEY, null);
                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
                assertNull(map.get(EXTRA_KEY), "wrong value");
                break;
            case OLDVALUE :
                map.put(EXTRA_KEY, VALUES[1]);
                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
                assertSame(map.get(EXTRA_KEY), VALUES[1], "wrong value");
                break;
            default:
                fail("unexpected old value");
        }

        String returned = map.merge(EXTRA_KEY,
            newValue == Merging.Value.NULL ? (String) null : VALUES[2],
            merger
            );

        // check result

        switch(result) {
            case NULL :
                assertNull(returned, "wrong value");
                break;
            case NEWVALUE :
                assertSame(returned, VALUES[2], "wrong value");
                break;
            case RESULT :
                assertSame(returned, VALUES[3], "wrong value");
                break;
            default:
                fail("unexpected new value");
        }

        // check map
        switch(put) {
            case ABSENT :
                assertFalse(map.containsKey(EXTRA_KEY), "key not absent");
                break;
            case NULL :
                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
                assertNull(map.get(EXTRA_KEY), "wrong value");
                break;
            case NEWVALUE :
                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
                assertSame(map.get(EXTRA_KEY), VALUES[2], "wrong value");
                break;
            case RESULT :
                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
                assertSame(map.get(EXTRA_KEY), VALUES[3], "wrong value");
                break;
            default:
                fail("unexpected new value");
        }
}
 
源代码16 项目: journaldev   文件: DistinctCharsCount.java
private static void printDistinctCharsWithCount(String input) {
	Map<Character, Integer> charsWithCountMap = new HashMap<>();

	// using Map merge method from Java 8
	for (char c : input.toCharArray())
		charsWithCountMap.merge(c, 1, Integer::sum);
	System.out.println(charsWithCountMap);

	// another way using latest Java enhancements and no for loop, a bit complex though
	List<Character> list = input.chars().mapToObj(c -> (char) c).collect(Collectors.toList());

	list.stream().forEach(c -> charsWithCountMap.merge(c, 1, Integer::sum));

	System.out.println(charsWithCountMap);

}
 
源代码17 项目: jdk8u-jdk   文件: Defaults.java
@Test(dataProvider = "MergeCases")
private void testMerge(String description, Map<IntegerEnum, String> map, Merging.Value oldValue, Merging.Value newValue, Merging.Merger merger, Merging.Value put, Merging.Value result) {
        // add and check initial conditions.
        switch(oldValue) {
            case ABSENT :
                map.remove(EXTRA_KEY);
                assertFalse(map.containsKey(EXTRA_KEY), "key not absent");
                break;
            case NULL :
                map.put(EXTRA_KEY, null);
                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
                assertNull(map.get(EXTRA_KEY), "wrong value");
                break;
            case OLDVALUE :
                map.put(EXTRA_KEY, VALUES[1]);
                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
                assertSame(map.get(EXTRA_KEY), VALUES[1], "wrong value");
                break;
            default:
                fail("unexpected old value");
        }

        String returned = map.merge(EXTRA_KEY,
            newValue == Merging.Value.NULL ? (String) null : VALUES[2],
            merger
            );

        // check result

        switch(result) {
            case NULL :
                assertNull(returned, "wrong value");
                break;
            case NEWVALUE :
                assertSame(returned, VALUES[2], "wrong value");
                break;
            case RESULT :
                assertSame(returned, VALUES[3], "wrong value");
                break;
            default:
                fail("unexpected new value");
        }

        // check map
        switch(put) {
            case ABSENT :
                assertFalse(map.containsKey(EXTRA_KEY), "key not absent");
                break;
            case NULL :
                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
                assertNull(map.get(EXTRA_KEY), "wrong value");
                break;
            case NEWVALUE :
                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
                assertSame(map.get(EXTRA_KEY), VALUES[2], "wrong value");
                break;
            case RESULT :
                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
                assertSame(map.get(EXTRA_KEY), VALUES[3], "wrong value");
                break;
            default:
                fail("unexpected new value");
        }
}
 
源代码18 项目: j2objc   文件: CollectionsTest.java
/**
 * Asserts that the given map is checked (rejects keys/values of type Object).
 *
 * @param map a checked Map that contains the entry (presentKey, preventValue), does not
 *            contain key absentKey or value absentValue, and rejects keys/types of type Object.
 */
private static<K,V> void check_map_isChecked(Map map,
        K presentKey, V presentValue, K absentKey, V absentValue) {
    Map copyOfMap = new HashMap(map);
    assertEquals(map.get(presentKey), presentValue);
    assertFalse(map.containsKey(absentKey));
    assertFalse(map.values().contains(absentValue));

    assertThrowsCce(() -> { map.replaceAll((k, v) -> new Object()); });

    assertThrowsCce(() -> { map.putIfAbsent(presentKey, new Object()); });
    assertThrowsCce(() -> { map.putIfAbsent(absentKey, new Object()); });
    assertThrowsCce(() -> { map.putIfAbsent(new Object(), presentValue); });

    assertThrowsCce(() -> { map.remove(new Object()); });

    assertThrowsCce(() -> { map.replace(new Object(), presentValue); });
    assertThrowsCce(() -> { map.replace(presentKey, new Object()); });

    assertThrowsCce(() -> { map.replace(new Object(), presentValue, absentValue); });
    // doesn't throw, but has no effect since oldValue doesn't match
    assertFalse(map.replace(presentKey, new Object(), absentValue));
    assertThrowsCce(() -> { map.replace(presentKey, presentValue, new Object()); });

    assertThrowsCce(() -> { map.computeIfAbsent(new Object(), k -> presentValue); });
    // doesn't throw, but has no effect since presentKey is present
    assertEquals(presentValue, map.computeIfAbsent(presentKey, k -> new Object()));
    assertThrowsCce(() -> { map.computeIfAbsent(absentKey, k -> new Object()); });

    assertThrowsCce(() -> { map.computeIfPresent(new Object(), (k, v) -> presentValue); });
    assertThrowsCce(() -> { map.computeIfPresent(presentKey, (k, v) -> new Object()); });
    // doesn't throw, but has no effect since absentKey is absent
    assertNull(map.computeIfPresent(absentKey, (k, v) -> new Object()));

    assertThrowsCce(() -> { map.compute(new Object(), (k, v) -> presentValue); });
    assertThrowsCce(() -> { map.compute(presentKey, (k, v) -> new Object()); });
    assertThrowsCce(() -> { map.compute(absentKey, (k, v) -> new Object()); });

    assertThrowsCce(() -> { map.merge(new Object(), presentValue, (v1, v2) -> presentValue); });
    assertThrowsCce(() -> { map.merge(presentKey, presentValue, (v1, v2) -> new Object()); });

    // doesn't throw, puts (absentKey, absentValue) into the map
    map.merge(absentKey, absentValue, (v1, v2) -> new Object());
    assertEquals(absentValue, map.remove(absentKey)); // restore previous state

    assertThrowsCce(() -> { map.put(new Object(), absentValue); });
    assertThrowsCce(() -> { map.put(absentKey, new Object()); });
    assertThrowsCce(() -> { map.put(new Object(), presentValue); });
    assertThrowsCce(() -> { map.put(presentKey, new Object()); });

    assertEquals("map should be unchanged", copyOfMap, map);
}
 
源代码19 项目: jdk8u-jdk   文件: Defaults.java
@Test(dataProvider = "MergeCases")
private void testMerge(String description, Map<IntegerEnum, String> map, Merging.Value oldValue, Merging.Value newValue, Merging.Merger merger, Merging.Value put, Merging.Value result) {
        // add and check initial conditions.
        switch(oldValue) {
            case ABSENT :
                map.remove(EXTRA_KEY);
                assertFalse(map.containsKey(EXTRA_KEY), "key not absent");
                break;
            case NULL :
                map.put(EXTRA_KEY, null);
                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
                assertNull(map.get(EXTRA_KEY), "wrong value");
                break;
            case OLDVALUE :
                map.put(EXTRA_KEY, VALUES[1]);
                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
                assertSame(map.get(EXTRA_KEY), VALUES[1], "wrong value");
                break;
            default:
                fail("unexpected old value");
        }

        String returned = map.merge(EXTRA_KEY,
            newValue == Merging.Value.NULL ? (String) null : VALUES[2],
            merger
            );

        // check result

        switch(result) {
            case NULL :
                assertNull(returned, "wrong value");
                break;
            case NEWVALUE :
                assertSame(returned, VALUES[2], "wrong value");
                break;
            case RESULT :
                assertSame(returned, VALUES[3], "wrong value");
                break;
            default:
                fail("unexpected new value");
        }

        // check map
        switch(put) {
            case ABSENT :
                assertFalse(map.containsKey(EXTRA_KEY), "key not absent");
                break;
            case NULL :
                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
                assertNull(map.get(EXTRA_KEY), "wrong value");
                break;
            case NEWVALUE :
                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
                assertSame(map.get(EXTRA_KEY), VALUES[2], "wrong value");
                break;
            case RESULT :
                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
                assertSame(map.get(EXTRA_KEY), VALUES[3], "wrong value");
                break;
            default:
                fail("unexpected new value");
        }
}
 
private void updateHook(Map<String, List<String>> alreadyExecutedHooks, List<HookPhase> currentHookPhasesForExecution, Hook hook) {
    List<String> hookPhasesBasedOnCurrentHookPhase = getHookPhasesBasedOnCurrentHookPhase(currentHookPhasesForExecution,
                                                                                          hook.getPhases());
    alreadyExecutedHooks.merge(hook.getName(), hookPhasesBasedOnCurrentHookPhase, ListUtils::union);
}