Skip to content

Commit

Permalink
Improve hashCode() implementation for Tuple*
Browse files Browse the repository at this point in the history
  • Loading branch information
pivovarit committed Aug 23, 2024
1 parent ccf32c2 commit eb1b388
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 6 deletions.
4 changes: 2 additions & 2 deletions generator/Generator.sc
Original file line number Diff line number Diff line change
Expand Up @@ -2236,7 +2236,7 @@ def generateMainClasses(): Unit = {

@Override
public int hashCode() {
return ${if (i == 0) "1" else if (i == 1) "Objects.hashCode(_1)" else s"""Objects.hash(${(1 to i).gen(j => s"_$j")(", ")})"""};
return ${if (i == 0) "1" else if (i == 1) "Objects.hashCode(_1)" else if (i == 2) "Objects.hashCode(_1) ^ Objects.hashCode(_2)" else s"""Objects.hash(${(1 to i).gen(j => s"_$j")(", ")})"""};
}

@Override
Expand Down Expand Up @@ -3715,7 +3715,7 @@ def generateTestClasses(): Unit = {
@$test
public void shouldComputeCorrectHashCode() {
final int actual = createTuple().hashCode();
final int expected = ${im.getType("java.util.Objects")}.${if (i == 1) "hashCode" else "hash"}($nullArgs);
final int expected = ${if (i == 2) s"new java.util.AbstractMap.SimpleEntry<>($nullArgs)" else im.getType("java.util.Objects")}.${if (i == 2) "hashCode()" else if (i == 1) s"hashCode($nullArgs)" else s"hash($nullArgs)"};
$assertThat(actual).isEqualTo(expected);
}

Expand Down
2 changes: 1 addition & 1 deletion src-gen/main/java/io/vavr/Tuple2.java
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ public boolean equals(Object o) {

@Override
public int hashCode() {
return Objects.hash(_1, _2);
return Objects.hashCode(_1) ^ Objects.hashCode(_2);
}

@Override
Expand Down
3 changes: 1 addition & 2 deletions src-gen/test/java/io/vavr/Tuple2Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import java.util.AbstractMap;
import java.util.Comparator;
import java.util.Map;
import java.util.Objects;
import org.junit.Test;

public class Tuple2Test {
Expand Down Expand Up @@ -237,7 +236,7 @@ public void shouldRecognizeNonEqualityPerComponent() {
@Test
public void shouldComputeCorrectHashCode() {
final int actual = createTuple().hashCode();
final int expected = Objects.hash(null, null);
final int expected = new java.util.AbstractMap.SimpleEntry<>(null, null).hashCode();
assertThat(actual).isEqualTo(expected);
}

Expand Down
2 changes: 1 addition & 1 deletion src/test/java/io/vavr/TupleTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public void shouldCreateTuple2FromEntry() {
@Test
public void shouldHashTuple2() {
final Tuple2<?, ?> t = tuple2();
assertThat(t.hashCode()).isEqualTo(Objects.hash(t._1, t._2));
assertThat(t.hashCode()).isEqualTo(new AbstractMap.SimpleEntry<>(t._1, t._2).hashCode());
}

@Test
Expand Down
7 changes: 7 additions & 0 deletions src/test/java/io/vavr/collection/AbstractMapTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1441,4 +1441,11 @@ public void shouldNonNilGroupByIdentity() {
assertThat(actual).isEqualTo(expected);
}

// -- hashCode

@Override
@Test
public void shouldCalculateDifferentHashCodesForDifferentTraversables() {
assertThat(mapOf('a', 2, 'b', 1).hashCode()).isNotEqualTo(mapOf('a', 1, 'b', 2).hashCode());
}
}
9 changes: 9 additions & 0 deletions src/test/java/io/vavr/collection/AbstractMultimapTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ protected <T1 extends Comparable<T1>, T2> Multimap<T1, T2> emptyMap() {

abstract protected <K extends Comparable<K>, V> Multimap<K, V> mapOfPairs(K k1, V v1, K k, V v2, K k3, V v3);

abstract protected <K extends Comparable<K>, V> Multimap<K, V> mapOf(K k1, V v1, K k2, V v2);

abstract protected <K extends Comparable<K>, V> Multimap<K, V> mapOf(K key, V value);

abstract protected <K extends Comparable<? super K>, V> Multimap<K, V> mapOf(java.util.Map<? extends K, ? extends V> map);
Expand Down Expand Up @@ -1198,4 +1200,11 @@ public void shouldCollectUsingMultimap() {
// java.lang.ClassCastException: io.vavr.collection.List$Cons cannot be cast to java.lang.Comparable
}

// -- hashCode

@Override
@Test
public void shouldCalculateDifferentHashCodesForDifferentTraversables() {
assertThat(mapOf("a", 2, "b", 1).hashCode()).isNotEqualTo(mapOf("a", 1, "b", 2).hashCode());
}
}
14 changes: 14 additions & 0 deletions src/test/java/io/vavr/collection/HashMultimapTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,20 @@ protected <K extends Comparable<K>, V> HashMultimap<K, V> mapOfPairs(K k1, V v1,
}
}

@Override
protected <K extends Comparable<K>, V> Multimap<K, V> mapOf(K k1, V v1, K k2, V v2) {
switch (containerType) {
case SEQ:
return HashMultimap.withSeq().of(k1, v1, k2, v2);
case SET:
return HashMultimap.withSet().of(k1, v1, k2, v2);
case SORTED_SET:
return HashMultimap.withSortedSet(Comparators.naturalComparator()).of(k1, v1, k2, v2);
default:
throw new RuntimeException();
}
}

@Override
protected <K extends Comparable<K>, V> HashMultimap<K, V> mapOf(K key, V value) {
switch (containerType) {
Expand Down
14 changes: 14 additions & 0 deletions src/test/java/io/vavr/collection/LinkedHashMultimapTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,20 @@ protected <K extends Comparable<K>, V> LinkedHashMultimap<K, V> mapOfPairs(K k1,
}
}

@Override
protected <K extends Comparable<K>, V> Multimap<K, V> mapOf(K k1, V v1, K k2, V v2) {
switch (containerType) {
case SEQ:
return LinkedHashMultimap.withSeq().of(k1, v1, k2, v2);
case SET:
return LinkedHashMultimap.withSet().of(k1, v1, k2, v2);
case SORTED_SET:
return LinkedHashMultimap.withSortedSet(Comparators.naturalComparator()).of(k1, v1, k2, v2);
default:
throw new RuntimeException();
}
}

@Override
protected <K extends Comparable<K>, V> LinkedHashMultimap<K, V> mapOf(K key, V value) {
switch (containerType) {
Expand Down
14 changes: 14 additions & 0 deletions src/test/java/io/vavr/collection/TreeMultimapTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,20 @@ protected <K extends Comparable<K>, V> TreeMultimap<K, V> mapOfPairs(K k1, V v1,
}
}

@Override
protected <K extends Comparable<K>, V> Multimap<K, V> mapOf(K k1, V v1, K k2, V v2) {
switch (containerType) {
case SEQ:
return TreeMultimap.withSeq().of(k1, v1, k2, v2);
case SET:
return TreeMultimap.withSet().of(k1, v1, k2, v2);
case SORTED_SET:
return TreeMultimap.withSortedSet(Comparators.naturalComparator()).of(k1, v1, k2, v2);
default:
throw new RuntimeException();
}
}

@Override
protected <K extends Comparable<K>, V> TreeMultimap<K, V> mapOf(K key, V value) {
switch (containerType) {
Expand Down

0 comments on commit eb1b388

Please sign in to comment.