@Before public void initFreqMap() { this.freqMap = new FreqMap(); freqMap.upsert("cat"); freqMap.upsert("cat"); freqMap.upsert("dog"); freqMap.upsert("cow"); freqMap.upsert("cow"); freqMap.upsert("catdog"); freqMap.upsert("catdog"); freqMap.upsert("catdog"); freqMap.upsert("cat"); freqMap.upsert("cat"); }
@Override protected FreqMap _apply(final FreqMap a, final FreqMap b) { for (final Entry<String, Long> entry : b.entrySet()) { if (a.containsKey(entry.getKey())) { a.put(entry.getKey(), a.get(entry.getKey()) + entry.getValue()); } else { a.put(entry.getKey(), entry.getValue()); } } return a; } }
/** * Adds a new key and value to the map if the key is not already there. * If the key is already there, the value supplied is added to the existing value for the key and the result is inserted into the map. * * @param key The key in the map to increment or insert. * @param value The value to increment by or initialise to. */ public void upsert(final String key, final Long value) { final Long currentValue = get(key); if (null == currentValue) { put(key, value); } else { put(key, currentValue + value); } }
/** * Creates a filtered copy of the map using a supplied predicate.<br> * Returns a copy of the map if predicate supplied is null. * * @param map The frequency map that is to be sorted through * @return A new frequency map with only the filtered entries present. */ private FreqMap filterPredicate(final FreqMap map) { final FreqMap f = new FreqMap(); if (predicate == null) { map.forEach(f::upsert); } else { map.entrySet().stream().filter(e -> predicate.test(e.getKey())) .forEach(e -> f.upsert(e.getKey(), e.getValue())); } return f; }
@Test public void shouldMergeFreqMaps() { // Given final FreqMapAggregator aggregator = new FreqMapAggregator(); final FreqMap freqMap1 = new FreqMap(); freqMap1.put("1", 2L); freqMap1.put("2", 3L); final FreqMap freqMap2 = new FreqMap(); freqMap2.put("2", 4L); freqMap2.put("3", 5L); // When final FreqMap result = aggregator.apply(freqMap1, freqMap2); // Then assertEquals((Long) 2L, result.get("1")); assertEquals((Long) 7L, result.get("2")); assertEquals((Long) 5L, result.get("3")); }
@Test public void shouldSkipEntryWithNullKey() throws SerialisationException { // Given final FreqMap freqMap = new FreqMap(); freqMap.put(null, 10L); freqMap.put("y", 5L); freqMap.put("z", 20L); // When final byte[] serialised = serialiser.serialise(freqMap); final FreqMap deserialised = serialiser.deserialise(serialised); assertFalse(deserialised.containsKey("x")); assertEquals((Long) 5L, deserialised.get("y")); assertEquals((Long) 20L, deserialised.get("z")); }
@Override public FreqMap deserialiseEmpty() { return new FreqMap(); } }
@Test public void testUpsertCreatesNewKeyValue() { //given final String key = "test"; final Long value = 6L; //when freqMap.upsert(key, value); //then assertTrue(freqMap.containsKey(key)); assertEquals(value, freqMap.get(key)); }
@Test public void shouldNotMutateOriginalValue() { //given final Regex predicate = new Regex("^\\wo\\w$"); final FreqMapPredicator fRegexPredicator = new FreqMapPredicator(predicate); //when final FreqMap fRegex = fRegexPredicator.apply(freqMap); //then assertEquals(fRegex.size(), 2); assertTrue(fRegex.containsKey("cow")); assertTrue(fRegex.containsKey("dog")); assertEquals(freqMap.size(), 4); assertTrue(freqMap.containsKey("cat")); assertTrue(freqMap.containsKey("dog")); assertTrue(freqMap.containsKey("catdog")); assertTrue(freqMap.containsKey("cow")); }
/** * Increments the value of an existing key by 1. * If the key doesn't exist, initialises the value to 1. * * @param key The key to increment or insert. */ public void upsert(final String key) { upsert(key, 1L); } }
@Override public Long apply(final FreqMap freqMap) { if (null != freqMap) { return freqMap.get(key); } return null; }
@Override public byte[] serialise(final FreqMap map) throws SerialisationException { Set<Entry<String, Long>> entrySet = map.entrySet(); ByteArrayOutputStream out = new ByteArrayOutputStream(); boolean isFirst = true; for (final Entry<String, Long> entry : entrySet) { if (null != entry.getKey() && null != entry.getValue()) { if (isFirst) { isFirst = false; } else { out.write(ByteArrayEscapeUtils.DELIMITER); } try { out.write(ByteArrayEscapeUtils.escape(entry.getKey().getBytes(CommonConstants.UTF_8))); } catch (final IOException e) { throw new SerialisationException("Failed to serialise a key from a FreqMap: " + entry.getKey(), e); } out.write(ByteArrayEscapeUtils.DELIMITER); try { out.write(ByteArrayEscapeUtils.escape(longSerialiser.serialise(entry.getValue()))); } catch (final IOException e) { throw new SerialisationException("Failed to serialise a value from a FreqMap: " + entry.getValue(), e); } } } return out.toByteArray(); }
@Test public void shouldSerialiseDeserialiseFreqMapWithAnEmptyKey() throws SerialisationException { // Given final FreqMap freqMap = new FreqMap(); freqMap.put("", 10L); freqMap.put("y", 5L); freqMap.put("z", 20L); // When final byte[] serialised = serialiser.serialise(freqMap); final FreqMap deserialised = serialiser.deserialise(serialised); assertEquals((Long) 10L, deserialised.get("")); assertEquals((Long) 5L, deserialised.get("y")); assertEquals((Long) 20L, deserialised.get("z")); }
@Test public void shouldSkipEntryWithNullValues() throws SerialisationException { // Given final FreqMap freqMap = new FreqMap(); freqMap.put("v", null); freqMap.put("w", 5L); freqMap.put("x", null); freqMap.put("y", 20L); freqMap.put("z", null); // When final byte[] serialised = serialiser.serialise(freqMap); final FreqMap deserialised = serialiser.deserialise(serialised); assertFalse(deserialised.containsKey("v")); assertEquals((Long) 5L, deserialised.get("w")); assertFalse(deserialised.containsKey("x")); assertEquals((Long) 20L, deserialised.get("y")); assertFalse(deserialised.containsKey("z")); }
@Override public FreqMap apply(final Object value) { return new FreqMap(null != value ? value.toString() : null); } }