Remove Comparable from the Shape class

The Shape could be used as a key so implements equals and hashCode. The
ordering of a Shape is arbitrary.
This commit is contained in:
Alex Herbert 2022-11-05 08:43:58 +00:00
parent f4d5690ca8
commit 9a6665af36
2 changed files with 38 additions and 23 deletions

View File

@ -16,8 +16,6 @@
*/
package org.apache.commons.collections4.bloomfilter;
import java.util.Objects;
/**
* The definition of a Bloom filter shape.
*
@ -43,7 +41,7 @@ import java.util.Objects;
* [Wikipedia]</a>
* @since 4.5
*/
public final class Shape implements Comparable<Shape> {
public final class Shape {
/**
* The natural logarithm of 2. Used in several calculations. Approximately 0.693147180559945.
@ -81,19 +79,20 @@ public final class Shape implements Comparable<Shape> {
}
@Override
public int compareTo(Shape other) {
int i = Integer.compare(numberOfBits, other.numberOfBits);
return i == 0 ? Integer.compare(numberOfHashFunctions, other.numberOfHashFunctions) : i;
}
@Override
public boolean equals(final Object o) {
return (o instanceof Shape) ? compareTo((Shape) o) == 0 : false;
public boolean equals(Object obj) {
// Shape is final so no check for the same class as inheritance is not possible
if (obj instanceof Shape) {
Shape other = (Shape) obj;
return numberOfBits == other.numberOfBits &&
numberOfHashFunctions == other.numberOfHashFunctions;
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(numberOfBits, numberOfHashFunctions);
// Match Arrays.hashCode(new int[] {numberOfBits, numberOfHashFunctions})
return (31 + numberOfBits) * 31 + numberOfHashFunctions;
}
/**

View File

@ -17,11 +17,16 @@
package org.apache.commons.collections4.bloomfilter;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.Arrays;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
/**
* Tests the {@link Shape} class.
@ -45,18 +50,29 @@ public class ShapeTest {
/**
* Test equality of shape.
*/
@Test
public void testEquals() {
@ParameterizedTest
@CsvSource({
"3, 24",
"1, 24",
"1, 1",
"13, 124",
"13, 224",
})
public void testEqualsAndHashCode(int k, int m) {
Shape shape1 = Shape.fromKM(k, m);
assertEquals(shape1, shape1);
assertEquals(Arrays.hashCode(new int[] {m, k}), shape1.hashCode(),
"Doesn't match Arrays.hashCode(new int[] {m, k})");
assertNotEquals(shape1, null);
assertNotEquals(shape1, "text");
assertNotEquals(shape1, Integer.valueOf(3));
assertNotEquals(shape1, Shape.fromKM(k, m + 1));
assertNotEquals(shape1, Shape.fromKM(k + 1, m));
assertEquals(shape, shape);
assertEquals(3, shape.getNumberOfHashFunctions());
assertEquals(24, shape.getNumberOfBits());
assertEquals(shape.hashCode(), Shape.fromKM(3, 24).hashCode());
assertNotEquals(shape, null);
assertNotEquals(shape, Shape.fromKM(3, 25));
assertNotEquals(shape, Shape.fromKM(4, 24));
assertNotEquals(shape, "text");
assertNotEquals(shape, Integer.valueOf(3));
// Test this is reproducible
Shape shape2 = Shape.fromKM(k, m);
assertEquals(shape1, shape2);
assertEquals(shape1.hashCode(), shape2.hashCode());
}
@Test