perf[hashmap]: ConcurrentHashMapLongObject equals and hashcode

This commit is contained in:
godotg
2024-07-02 15:10:57 +08:00
parent 0c0dc62c2b
commit 3cb3f304df
3 changed files with 117 additions and 54 deletions
@@ -191,20 +191,61 @@ public class ConcurrentHashMapLongObject<V> implements Map<Long, V> {
}
}
private Map<Long, V> copyMap() {
var copyMap = new HashMap<Long, V>();
for (var i = 0; i < buckets; i++) {
var readLock = locks[i].readLock();
var map = maps.get(i);
readLock.lock();
try {
copyMap.putAll(map);
} finally {
readLock.unlock();
}
}
return copyMap;
}
@Override
public Set<Long> keySet() {
throw new UnsupportedOperationException();
return copyMap().keySet();
}
@Override
public Collection<V> values() {
throw new UnsupportedOperationException();
return copyMap().values();
}
@Override
public Set<Entry<Long, V>> entrySet() {
throw new UnsupportedOperationException();
return copyMap().entrySet();
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Map<?, ?> m)) {
return false;
}
if (m.size() != size()) {
return false;
}
for (var entry : m.entrySet()) {
var key = entry.getKey();
var value = entry.getValue();
if (!containsKey(key)) {
return false;
}
if (!Objects.equals(value, get(key))) {
return false;
}
}
return true;
}
@Override
public int hashCode() {
return super.hashCode();
}
}
@@ -0,0 +1,73 @@
/*
* Copyright (C) 2020 The zfoo Authors
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.collection;
import com.zfoo.protocol.collection.concurrent.ConcurrentHashMapLongObject;
import com.zfoo.protocol.collection.concurrent.CopyOnWriteHashMap;
import com.zfoo.protocol.collection.concurrent.CopyOnWriteHashMapLongObject;
import io.netty.util.collection.LongObjectHashMap;
import org.junit.Assert;
import org.junit.Test;
import java.util.Map;
/**
* @author godotg
*/
public class ConcurrentHashMapTest {
@Test
public void equalsMapTest() {
var map = Map.of(1L, "a", 2L, "b", 3L, "c");
var concurrentHashMapLongObject = new ConcurrentHashMapLongObject<String>();
concurrentHashMapLongObject.putAll(map);
Assert.assertEquals(map, concurrentHashMapLongObject);
var copyOnWriteHashMap = new CopyOnWriteHashMap<Long, String>();
copyOnWriteHashMap.putAll(map);
Assert.assertEquals(map, copyOnWriteHashMap);
var copyOnWriteHashMapLongObject = new CopyOnWriteHashMapLongObject<String>();
copyOnWriteHashMapLongObject.putAll(map);
Assert.assertEquals(map, concurrentHashMapLongObject);
}
@Test
public void primitiveMapTest() {
var map = new LongObjectHashMap<Integer>();
var startTime = System.currentTimeMillis();
var num = 10;
for (int i = 0; i < 100; i++) {
for (int j = 0; j < num; j++) {
map.put(j, j);
}
for (var entry : map.entrySet()) {
var key = entry.getKey();
var value = entry.getValue();
}
for (int j = 0; j < num; j++) {
var value = (int) map.get((long) j);
Assert.assertEquals(value, j);
}
for (int j = 0; j < num; j++) {
map.remove((long) j);
}
}
System.out.println(System.currentTimeMillis() - startTime);
}
}
@@ -233,55 +233,4 @@ public class ConcurrentTesting {
System.out.println(atomicCount.get());
}
// -----------------------------------------------------------------------------------------------------------------
@Test
public void primitiveMapTest() {
var map = new LongObjectHashMap<Integer>();
var startTime = System.currentTimeMillis();
for (int count = 0; count < maxCount; count++) {
for (int j = 0; j < num; j++) {
map.put(j, j);
}
for (var entry : map.entrySet()) {
var key = entry.getKey();
var value = entry.getValue();
}
for (int j = 0; j < num; j++) {
var value = (int) map.get((long) j);
Assert.assertEquals(value, j);
}
for (int j = 0; j < num; j++) {
map.remove((long) j);
}
}
System.out.println(System.currentTimeMillis() - startTime);
}
@Test
public void mapTest() {
var map = new HashMap<Long, Integer>();
var startTime = System.currentTimeMillis();
for (int count = 0; count < maxCount; count++) {
for (int j = 0; j < num; j++) {
map.put((long) j, j);
}
for (var entry : map.entrySet()) {
var key = entry.getKey();
var value = entry.getValue();
}
for (int j = 0; j < num; j++) {
var value = (int) map.get((long) j);
Assert.assertEquals(value, j);
}
for (int j = 0; j < num; j++) {
map.remove((long) j);
}
}
System.out.println(System.currentTimeMillis() - startTime);
}
}