util: LinkedHashMapRemoveEldest refactored with BiConsumer

This commit is contained in:
Sergey Matvienko 2021-05-18 13:07:53 +03:00 committed by Andrew Shvayka
parent d7f797a065
commit 3d3aae60d8
2 changed files with 29 additions and 37 deletions

View File

@ -36,48 +36,33 @@ import lombok.ToString;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.BiConsumer;
/**
* HashMap that removed eldest (by put order) entries
* LinkedHashMap that removed eldest entries (by insert order)
* It guaranteed that size is not greater then maxEntries parameter. And remove time is constant O(1).
* Use withMaxEntries to setup maxEntries.
* Because overloaded constructor will look similar to LinkedHashMap(initCapacity)
* Example:
* new LinkedHashMapRemoveEldest<Long, String>().withMaxEntries(100L)
* LinkedHashMapRemoveEldest<Long, String> map =
* new LinkedHashMapRemoveEldest<>(MAX_ENTRIES, this::removeConsumer);
* */
@Getter
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class LinkedHashMapRemoveEldest<K,V> extends LinkedHashMap<K,V> {
long maxEntries = Long.MAX_VALUE;
public class LinkedHashMapRemoveEldest<K, V> extends LinkedHashMap<K, V> {
final long maxEntries;
final BiConsumer<K, V> removeConsumer;
public LinkedHashMapRemoveEldest() {
super();
}
public LinkedHashMapRemoveEldest(int initialCapacity) {
super(initialCapacity);
}
public LinkedHashMapRemoveEldest(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
}
public LinkedHashMapRemoveEldest(Map<? extends K, ? extends V> m) {
super(m);
}
public LinkedHashMapRemoveEldest(int initialCapacity, float loadFactor, boolean accessOrder) {
super(initialCapacity, loadFactor, accessOrder);
}
public LinkedHashMapRemoveEldest<K,V> withMaxEntries(long maxEntries) {
public LinkedHashMapRemoveEldest(long maxEntries, BiConsumer<K, V> removeConsumer) {
this.maxEntries = maxEntries;
return this;
this.removeConsumer = removeConsumer;
}
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > maxEntries;
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
if (size() <= maxEntries) {
return false;
}
removeConsumer.accept(eldest.getKey(), eldest.getValue());
return true;
}
}

View File

@ -30,7 +30,7 @@
*/
package org.thingsboard.common.util;
import org.junit.Before;
import org.hamcrest.Matchers;
import org.junit.Test;
import java.util.LinkedHashMap;
@ -42,26 +42,33 @@ import static org.hamcrest.MatcherAssert.assertThat;
public class LinkedHashMapRemoveEldestTest {
public static final long MAX_ENTRIES = 10L;
LinkedHashMapRemoveEldest<Long, String> map;
long removeCount = 0;
@Before
public void setUp() throws Exception {
map = new LinkedHashMapRemoveEldest<Long, String>().withMaxEntries(MAX_ENTRIES);
void removeConsumer(Long id, String name) {
removeCount++;
assertThat(id, is(Matchers.lessThan(MAX_ENTRIES)));
assertThat(name, is(id.toString()));
}
@Test
public void givenMap_whenOverSized_thenVerifyRemovedEldest() {
//given
LinkedHashMapRemoveEldest<Long, String> map =
new LinkedHashMapRemoveEldest<>(MAX_ENTRIES, this::removeConsumer);
assertThat(map.getMaxEntries(), is(MAX_ENTRIES));
assertThat(map, instanceOf(LinkedHashMap.class));
assertThat(map, instanceOf(LinkedHashMapRemoveEldest.class));
assertThat(map.size(), is(0));
//when
for (long i = 0; i < MAX_ENTRIES * 2; i++) {
map.put(i, String.valueOf(i));
}
assertThat(map.size(), is((int) MAX_ENTRIES));
//then
assertThat((long) map.size(), is(MAX_ENTRIES));
assertThat(removeCount, is(MAX_ENTRIES));
for (long i = MAX_ENTRIES; i < MAX_ENTRIES * 2; i++) {
assertThat(map.get(i), is(String.valueOf(i)));
}