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.LinkedHashMap;
import java.util.Map; 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). * 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: * Example:
* new LinkedHashMapRemoveEldest<Long, String>().withMaxEntries(100L) * LinkedHashMapRemoveEldest<Long, String> map =
* new LinkedHashMapRemoveEldest<>(MAX_ENTRIES, this::removeConsumer);
* */ * */
@Getter @Getter
@ToString(callSuper = true) @ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class LinkedHashMapRemoveEldest<K,V> extends LinkedHashMap<K,V> { public class LinkedHashMapRemoveEldest<K, V> extends LinkedHashMap<K, V> {
long maxEntries = Long.MAX_VALUE; final long maxEntries;
final BiConsumer<K, V> removeConsumer;
public LinkedHashMapRemoveEldest() { public LinkedHashMapRemoveEldest(long maxEntries, BiConsumer<K, V> removeConsumer) {
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) {
this.maxEntries = maxEntries; this.maxEntries = maxEntries;
return this; this.removeConsumer = removeConsumer;
} }
@Override @Override
protected boolean removeEldestEntry(Map.Entry eldest) { protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > maxEntries; if (size() <= maxEntries) {
return false;
}
removeConsumer.accept(eldest.getKey(), eldest.getValue());
return true;
} }
} }

View File

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