BAEL-5167: add sample key implementations and test the correct functionality and the performance of those keys in a HashMap (#11260)

This commit is contained in:
Ralf Ueberfuhr 2021-09-28 05:58:14 +02:00 committed by GitHub
parent 5276659f6f
commit 7b47645746
8 changed files with 246 additions and 1 deletions

View File

@ -0,0 +1,6 @@
## Java Collections Cookbooks and Examples
This module contains articles about Map data structures in Java.
### Relevant Articles:
- [Using a Custom Class as a Key in a Java HashMap](https://www.baeldung.com/custom-key-hashmap)

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>core-java-collections-maps-4</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>core-java-collections-maps-4</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung.core-java-modules</groupId>
<artifactId>core-java-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<!-- those tests are not made for CI purposes, but for manual testing -->
<groups>!performance</groups>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@ -0,0 +1,39 @@
package com.baeldung.maps;
import java.util.Objects;
public class CoordinateKey {
private final int x;
private final int y;
private final int hashCode;
public CoordinateKey(int x, int y) {
this.x = x;
this.y = y;
this.hashCode = Objects.hash(x, y);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
CoordinateKey that = (CoordinateKey) o;
return x == that.x && y == that.y;
}
@Override
public int hashCode() {
return this.hashCode;
}
}

View File

@ -0,0 +1,45 @@
package com.baeldung.maps;
import java.util.Objects;
public class CoordinateMutableKey {
private int x;
private int y;
public CoordinateMutableKey(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
CoordinateMutableKey that = (CoordinateMutableKey) o;
return x == that.x && y == that.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}

View File

@ -0,0 +1,13 @@
package com.baeldung.maps;
public class CoordinateSlowKey extends CoordinateKey {
public CoordinateSlowKey(int x, int y) {
super(x, y);
}
@Override
public int hashCode() {
return 1;
}
}

View File

@ -0,0 +1,80 @@
package com.baeldung.maps;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import java.awt.*;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
public class CoordinateKeyUnitTest {
private Map<CoordinateKey, Color> pixels = new HashMap<>();
@Test
void testOptimalKey() {
// setup
CoordinateKey coord = new CoordinateKey(1, 2);
pixels.put(coord, Color.CYAN);
// read out color correctly
assertEquals(Color.CYAN, pixels.get(coord));
}
@Test
void testSlowKey() {
// setup
CoordinateKey coord = new CoordinateSlowKey(1, 2);
pixels.put(coord, Color.CYAN);
// read out color correctly
assertEquals(Color.CYAN, pixels.get(coord));
}
// Performance Test Parameters - change here
private static final int MAX_X = 100;
private static final int MAX_Y = 100;
private static final int COUNT_OF_QUERIES = 1000;
private static final int QUERY_X = 1;
private static final int QUERY_Y = 1;
@Tag("performance")
@Test
void testKeyPerformance() {
// generate some sample keys and values
for (int x = 0; x < MAX_X; x++) {
for (int y = 0; y < MAX_Y; y++) {
pixels.put(new CoordinateKey(x, y), new Color(x % 255, y % 255, (x + y) % 255));
}
}
// read out multiple times and measure time
CoordinateKey coord = new CoordinateKey(QUERY_X, QUERY_Y);
long t1 = System.currentTimeMillis();
for (int i = 0; i < COUNT_OF_QUERIES; i++) {
assertNotNull(pixels.get(coord));
}
long t2 = System.currentTimeMillis();
System.out.printf("Optimal key performance: %d ms%n", t2 - t1);
}
@Tag("performance")
@Test
void testSlowKeyPerformance() {
// generate some sample keys and values
for (int x = 0; x < MAX_X; x++) {
for (int y = 0; y < MAX_Y; y++) {
pixels.put(new CoordinateSlowKey(x, y), new Color(x % 255, y % 255, (x + y) % 255));
}
}
// read out multiple times and measure time
CoordinateKey coord = new CoordinateSlowKey(QUERY_X, QUERY_Y);
long t1 = System.currentTimeMillis();
for (int i = 0; i < COUNT_OF_QUERIES; i++) {
assertNotNull(pixels.get(coord));
}
long t2 = System.currentTimeMillis();
System.out.printf("Slow key performance: %d ms%n", t2 - t1);
}
}

View File

@ -0,0 +1,27 @@
package com.baeldung.maps;
import org.junit.jupiter.api.Test;
import java.awt.*;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
public class CoordinateMutableKeyUnitTest {
@Test
void testKeyMutable() {
// setup
Map<CoordinateMutableKey, Color> pixels = new HashMap<>();
CoordinateMutableKey coord = new CoordinateMutableKey(1, 2);
pixels.put(coord, Color.CYAN);
// read out color correctly
assertEquals(Color.CYAN, pixels.get(coord));
// change key's hashcode should result in null value
coord.setX(10);
assertNull(pixels.get(coord));
}
}

View File

@ -38,6 +38,7 @@
<module>core-java-collections-maps</module>
<module>core-java-collections-maps-2</module>
<module>core-java-collections-maps-3</module>
<module>core-java-collections-maps-4</module>
<module>core-java-concurrency-2</module>
<module>core-java-concurrency-advanced</module>
<module>core-java-concurrency-advanced-2</module>
@ -138,4 +139,4 @@
<junit-jupiter.version>5.6.2</junit-jupiter.version>
</properties>
</project>
</project>