From d7f797a0650958cbee5e5e39a0f571190237fce5 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Tue, 18 May 2021 12:15:14 +0300 Subject: [PATCH] util: LinkedHashMapRemoveEldest implemented with test --- common/util/pom.xml | 5 ++ .../util/LinkedHashMapRemoveEldest.java | 83 +++++++++++++++++++ .../util/LinkedHashMapRemoveEldestTest.java | 70 ++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 common/util/src/main/java/org/thingsboard/common/util/LinkedHashMapRemoveEldest.java create mode 100644 common/util/src/test/java/org/thingsboard/common/util/LinkedHashMapRemoveEldestTest.java diff --git a/common/util/pom.xml b/common/util/pom.xml index 8a0fa1705b..26c4b42920 100644 --- a/common/util/pom.xml +++ b/common/util/pom.xml @@ -74,6 +74,11 @@ junit test + + org.hamcrest + hamcrest + test + org.mockito mockito-core diff --git a/common/util/src/main/java/org/thingsboard/common/util/LinkedHashMapRemoveEldest.java b/common/util/src/main/java/org/thingsboard/common/util/LinkedHashMapRemoveEldest.java new file mode 100644 index 0000000000..7f91da737b --- /dev/null +++ b/common/util/src/main/java/org/thingsboard/common/util/LinkedHashMapRemoveEldest.java @@ -0,0 +1,83 @@ +/** + * ThingsBoard, Inc. ("COMPANY") CONFIDENTIAL + * + * Copyright © 2016-2021 ThingsBoard, Inc. All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of ThingsBoard, Inc. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to ThingsBoard, Inc. + * and its suppliers and may be covered by U.S. and Foreign Patents, + * patents in process, and are protected by trade secret or copyright law. + * + * Dissemination of this information or reproduction of this material is strictly forbidden + * unless prior written permission is obtained from COMPANY. + * + * Access to the source code contained herein is hereby forbidden to anyone except current COMPANY employees, + * managers or contractors who have executed Confidentiality and Non-disclosure agreements + * explicitly covering such access. + * + * The copyright notice above does not evidence any actual or intended publication + * or disclosure of this source code, which includes + * information that is confidential and/or proprietary, and is a trade secret, of COMPANY. + * ANY REPRODUCTION, MODIFICATION, DISTRIBUTION, PUBLIC PERFORMANCE, + * OR PUBLIC DISPLAY OF OR THROUGH USE OF THIS SOURCE CODE WITHOUT + * THE EXPRESS WRITTEN CONSENT OF COMPANY IS STRICTLY PROHIBITED, + * AND IN VIOLATION OF APPLICABLE LAWS AND INTERNATIONAL TREATIES. + * THE RECEIPT OR POSSESSION OF THIS SOURCE CODE AND/OR RELATED INFORMATION + * DOES NOT CONVEY OR IMPLY ANY RIGHTS TO REPRODUCE, DISCLOSE OR DISTRIBUTE ITS CONTENTS, + * OR TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT MAY DESCRIBE, IN WHOLE OR IN PART. + */ +package org.thingsboard.common.util; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * HashMap that removed eldest (by put order) entries + * 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().withMaxEntries(100L) + * */ +@Getter +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class LinkedHashMapRemoveEldest extends LinkedHashMap { + long maxEntries = Long.MAX_VALUE; + + public LinkedHashMapRemoveEldest() { + super(); + } + + public LinkedHashMapRemoveEldest(int initialCapacity) { + super(initialCapacity); + } + + public LinkedHashMapRemoveEldest(int initialCapacity, float loadFactor) { + super(initialCapacity, loadFactor); + } + + public LinkedHashMapRemoveEldest(Map m) { + super(m); + } + + public LinkedHashMapRemoveEldest(int initialCapacity, float loadFactor, boolean accessOrder) { + super(initialCapacity, loadFactor, accessOrder); + } + + public LinkedHashMapRemoveEldest withMaxEntries(long maxEntries) { + this.maxEntries = maxEntries; + return this; + } + + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > maxEntries; + } +} diff --git a/common/util/src/test/java/org/thingsboard/common/util/LinkedHashMapRemoveEldestTest.java b/common/util/src/test/java/org/thingsboard/common/util/LinkedHashMapRemoveEldestTest.java new file mode 100644 index 0000000000..4dad070ec4 --- /dev/null +++ b/common/util/src/test/java/org/thingsboard/common/util/LinkedHashMapRemoveEldestTest.java @@ -0,0 +1,70 @@ +/** + * ThingsBoard, Inc. ("COMPANY") CONFIDENTIAL + * + * Copyright © 2016-2021 ThingsBoard, Inc. All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of ThingsBoard, Inc. and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to ThingsBoard, Inc. + * and its suppliers and may be covered by U.S. and Foreign Patents, + * patents in process, and are protected by trade secret or copyright law. + * + * Dissemination of this information or reproduction of this material is strictly forbidden + * unless prior written permission is obtained from COMPANY. + * + * Access to the source code contained herein is hereby forbidden to anyone except current COMPANY employees, + * managers or contractors who have executed Confidentiality and Non-disclosure agreements + * explicitly covering such access. + * + * The copyright notice above does not evidence any actual or intended publication + * or disclosure of this source code, which includes + * information that is confidential and/or proprietary, and is a trade secret, of COMPANY. + * ANY REPRODUCTION, MODIFICATION, DISTRIBUTION, PUBLIC PERFORMANCE, + * OR PUBLIC DISPLAY OF OR THROUGH USE OF THIS SOURCE CODE WITHOUT + * THE EXPRESS WRITTEN CONSENT OF COMPANY IS STRICTLY PROHIBITED, + * AND IN VIOLATION OF APPLICABLE LAWS AND INTERNATIONAL TREATIES. + * THE RECEIPT OR POSSESSION OF THIS SOURCE CODE AND/OR RELATED INFORMATION + * DOES NOT CONVEY OR IMPLY ANY RIGHTS TO REPRODUCE, DISCLOSE OR DISTRIBUTE ITS CONTENTS, + * OR TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT MAY DESCRIBE, IN WHOLE OR IN PART. + */ +package org.thingsboard.common.util; + +import org.junit.Before; +import org.junit.Test; + +import java.util.LinkedHashMap; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +public class LinkedHashMapRemoveEldestTest { + + public static final long MAX_ENTRIES = 10L; + LinkedHashMapRemoveEldest map; + + @Before + public void setUp() throws Exception { + map = new LinkedHashMapRemoveEldest().withMaxEntries(MAX_ENTRIES); + } + + @Test + public void givenMap_whenOverSized_thenVerifyRemovedEldest() { + assertThat(map.getMaxEntries(), is(MAX_ENTRIES)); + assertThat(map, instanceOf(LinkedHashMap.class)); + assertThat(map, instanceOf(LinkedHashMapRemoveEldest.class)); + assertThat(map.size(), is(0)); + + for (long i = 0; i < MAX_ENTRIES * 2; i++) { + map.put(i, String.valueOf(i)); + } + + assertThat(map.size(), is((int) MAX_ENTRIES)); + + for (long i = MAX_ENTRIES; i < MAX_ENTRIES * 2; i++) { + assertThat(map.get(i), is(String.valueOf(i))); + } + } + +} \ No newline at end of file