BAEL-4716 HashMap optimization (#10479)
This commit is contained in:
parent
65520720aa
commit
ba83b760d3
|
@ -0,0 +1,6 @@
|
||||||
|
package com.baeldung.map.hashing;
|
||||||
|
|
||||||
|
class Member {
|
||||||
|
Integer id;
|
||||||
|
String name;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.baeldung.map.hashing;
|
||||||
|
|
||||||
|
public class MemberWithBadHashing extends Member {
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return name.hashCode();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.baeldung.map.hashing;
|
||||||
|
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
|
import com.google.common.hash.HashFunction;
|
||||||
|
import com.google.common.hash.Hashing;
|
||||||
|
|
||||||
|
public class MemberWithGuavaHashing extends Member {
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
HashFunction hashFunction = Hashing.murmur3_32();
|
||||||
|
return hashFunction.newHasher()
|
||||||
|
.putInt(id)
|
||||||
|
.putString(name, Charsets.UTF_8)
|
||||||
|
.hash().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.baeldung.map.hashing;
|
||||||
|
|
||||||
|
public class MemberWithId extends Member {
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
MemberWithId that = (MemberWithId) o;
|
||||||
|
|
||||||
|
return id.equals(that.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.baeldung.map.hashing;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class MemberWithIdAndName extends Member {
|
||||||
|
public static final int PRIME = 31;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
MemberWithObjects that = (MemberWithObjects) o;
|
||||||
|
return Objects.equals(id, that.id) &&
|
||||||
|
Objects.equals(name, that.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = id.hashCode();
|
||||||
|
result = PRIME * result + (name == null ? 0 : name.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.baeldung.map.hashing;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class MemberWithObjects extends Member {
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
MemberWithObjects that = (MemberWithObjects) o;
|
||||||
|
return Objects.equals(id, that.id) &&
|
||||||
|
Objects.equals(name, that.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id, name);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
package com.baeldung.map.hashing;
|
||||||
|
|
||||||
|
import com.google.common.base.Stopwatch;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.SplittableRandom;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class HashingUnitTest {
|
||||||
|
|
||||||
|
public static final int SAMPLES = 1000000;
|
||||||
|
private SplittableRandom random = new SplittableRandom();
|
||||||
|
|
||||||
|
private String[] names = {"John", "Adam", "Suzie"};
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenPrimitiveByteArrayKey_whenRetrievingFromMap_shouldRetrieveDifferentObjects() {
|
||||||
|
// bad hashing example is prohibitively slow for bigger samples
|
||||||
|
// Duration[] badHashing = testDuration(MemberWithBadHashing::new);
|
||||||
|
Duration[] withId = testDuration(MemberWithId::new);
|
||||||
|
Duration[] withObjects = testDuration(MemberWithObjects::new);
|
||||||
|
Duration[] withIdAndName = testDuration(MemberWithIdAndName::new);
|
||||||
|
|
||||||
|
// System.out.println("Inserting with bad hashing:");
|
||||||
|
// System.out.println(badHashing[0]);
|
||||||
|
// System.out.println("Getting with bad hashing:");
|
||||||
|
// System.out.println(badHashing[1]);
|
||||||
|
|
||||||
|
System.out.println("Inserting with id hashing:");
|
||||||
|
System.out.println(withId[0]);
|
||||||
|
System.out.println("Getting with id hashing:");
|
||||||
|
System.out.println(withId[1]);
|
||||||
|
|
||||||
|
System.out.println("Inserting with id and name hashing:");
|
||||||
|
System.out.println(withIdAndName[0]);
|
||||||
|
System.out.println("Getting with id and name hashing:");
|
||||||
|
System.out.println(withIdAndName[1]);
|
||||||
|
|
||||||
|
System.out.println("Inserting with Objects hashing:");
|
||||||
|
System.out.println(withObjects[0]);
|
||||||
|
System.out.println("Getting with Objects hashing:");
|
||||||
|
System.out.println(withObjects[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String randomName() {
|
||||||
|
return names[random.nextInt(2)];
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends Member> Duration[] testDuration(Supplier<T> factory) {
|
||||||
|
HashMap<T, String> map = new HashMap<>();
|
||||||
|
Stopwatch stopwatch = Stopwatch.createUnstarted();
|
||||||
|
|
||||||
|
stopwatch.start();
|
||||||
|
for(int i = 0; i < SAMPLES; i++) {
|
||||||
|
T member = factory.get();
|
||||||
|
member.id = i;
|
||||||
|
member.name = randomName();
|
||||||
|
map.put(member, member.name);
|
||||||
|
}
|
||||||
|
stopwatch.stop();
|
||||||
|
Duration elapsedInserting = stopwatch.elapsed();
|
||||||
|
stopwatch.reset();
|
||||||
|
|
||||||
|
stopwatch.start();
|
||||||
|
for (T key : map.keySet()) {
|
||||||
|
map.get(key);
|
||||||
|
}
|
||||||
|
stopwatch.stop();
|
||||||
|
Duration elapsedGetting = stopwatch.elapsed();
|
||||||
|
stopwatch.reset();
|
||||||
|
|
||||||
|
return new Duration[]{elapsedInserting, elapsedGetting};
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue