diff --git a/core-java-modules/core-java-collections-maps-4/README.md b/core-java-modules/core-java-collections-maps-4/README.md new file mode 100644 index 0000000000..4449d3859b --- /dev/null +++ b/core-java-modules/core-java-collections-maps-4/README.md @@ -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) diff --git a/core-java-modules/core-java-collections-maps-4/pom.xml b/core-java-modules/core-java-collections-maps-4/pom.xml new file mode 100644 index 0000000000..1835e3ceac --- /dev/null +++ b/core-java-modules/core-java-collections-maps-4/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + core-java-collections-maps-4 + 0.1.0-SNAPSHOT + core-java-collections-maps-4 + jar + + + com.baeldung.core-java-modules + core-java-modules + 0.0.1-SNAPSHOT + ../pom.xml + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + !performance + + + + + + + diff --git a/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/maps/CoordinateKey.java b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/maps/CoordinateKey.java new file mode 100644 index 0000000000..34ae3d7952 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/maps/CoordinateKey.java @@ -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; + } +} diff --git a/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/maps/CoordinateMutableKey.java b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/maps/CoordinateMutableKey.java new file mode 100644 index 0000000000..08b329de3d --- /dev/null +++ b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/maps/CoordinateMutableKey.java @@ -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); + } +} diff --git a/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/maps/CoordinateSlowKey.java b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/maps/CoordinateSlowKey.java new file mode 100644 index 0000000000..9fe54bd9ea --- /dev/null +++ b/core-java-modules/core-java-collections-maps-4/src/main/java/com/baeldung/maps/CoordinateSlowKey.java @@ -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; + } +} diff --git a/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/maps/CoordinateKeyUnitTest.java b/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/maps/CoordinateKeyUnitTest.java new file mode 100644 index 0000000000..8ee68c4a3d --- /dev/null +++ b/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/maps/CoordinateKeyUnitTest.java @@ -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 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); + } + +} diff --git a/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/maps/CoordinateMutableKeyUnitTest.java b/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/maps/CoordinateMutableKeyUnitTest.java new file mode 100644 index 0000000000..54a61be230 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-4/src/test/java/com/baeldung/maps/CoordinateMutableKeyUnitTest.java @@ -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 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)); + } + +} diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index b272d2aa13..5291c8c3ca 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -38,6 +38,7 @@ core-java-collections-maps core-java-collections-maps-2 core-java-collections-maps-3 + core-java-collections-maps-4 core-java-concurrency-2 core-java-concurrency-advanced core-java-concurrency-advanced-2 @@ -138,4 +139,4 @@ 5.6.2 - \ No newline at end of file +