Skip to content

Commit

Permalink
Merge pull request #121 from nitsanw/hashset-equals
Browse files Browse the repository at this point in the history
[Java] Make hashset (int and object) Set::equals compatible
  • Loading branch information
mjpt777 authored Dec 18, 2017
2 parents 7b72974 + 814a5bf commit 34d25cc
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 59 deletions.
24 changes: 23 additions & 1 deletion agrona/src/main/java/org/agrona/collections/IntHashSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,29 @@ public boolean equals(final Object other)
containsAll(otherSet);
}

return false;
if (!(other instanceof Set))
{
return false;
}

final Set<?> c = (Set<?>)other;
if (c.size() != size())
{
return false;
}

try
{
return containsAll(c);
}
catch (final ClassCastException unused)
{
return false;
}
catch (final @DoNotSub NullPointerException unused)
{
return false;
}
}

/**
Expand Down
24 changes: 23 additions & 1 deletion agrona/src/main/java/org/agrona/collections/ObjectHashSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,29 @@ public boolean equals(final Object other)
return otherSet.size == size && containsAll(otherSet);
}

return false;
if (!(other instanceof Set))
{
return false;
}

final Set<?> c = (Set<?>)other;
if (c.size() != size())
{
return false;
}

try
{
return containsAll(c);
}
catch (final ClassCastException unused)
{
return false;
}
catch (final NullPointerException unused)
{
return false;
}
}

/**
Expand Down
137 changes: 80 additions & 57 deletions agrona/src/test/java/org/agrona/collections/IntHashSetTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -626,63 +626,6 @@ public void removeElementsFromIterator()
assertThat(testSet, hasSize(1));
}

private static void addTwoElements(final IntHashSet obj)
{
obj.add(1);
obj.add(1001);
}

private static void addTwoElements(final HashSet<Integer> obj)
{
obj.add(1);
obj.add(1001);
}

private void assertIteratorHasElements()
{
final Iterator<Integer> iter = testSet.iterator();

final Set<Integer> values = new HashSet<>();

assertTrue(iter.hasNext());
values.add(iter.next());
assertTrue(iter.hasNext());
values.add(iter.next());
assertFalse(iter.hasNext());

assertContainsElements(values);
}

private void assertIteratorHasElementsWithoutHasNext()
{
final Iterator<Integer> iter = testSet.iterator();

final Set<Integer> values = new HashSet<>();

values.add(iter.next());
values.add(iter.next());

assertContainsElements(values);
}

private static void assertArrayContainingElements(final Integer[] result)
{
assertThat(result, arrayContainingInAnyOrder(1, 1001));
}

private static void assertContainsElements(final Set<Integer> other)
{
assertThat(other, containsInAnyOrder(1, 1001));
}

private void exhaustIterator()
{
final IntIterator iterator = testSet.iterator();
iterator.next();
iterator.next();
iterator.next();
}

@Test
public void shouldNotContainMissingValueInitially()
{
Expand Down Expand Up @@ -861,4 +804,84 @@ public void shouldRemoveMissingValueWhenCleared()

assertFalse(testSet.contains(MISSING_VALUE));
}

@Test
public void shouldHaveCompatibleEqualsAndHashcode()
{
final HashSet compatibleSet = new HashSet();
final long seed = System.nanoTime();
final Random r = new Random(seed);
for (int i = 0; i < 1024; i++)
{
final int value = r.nextInt();
compatibleSet.add(value);
testSet.add(value);
}

if (r.nextBoolean())
{
compatibleSet.add(MISSING_VALUE);
testSet.add(MISSING_VALUE);
}
assertEquals("Fail with seed:" + seed, testSet, compatibleSet);
assertEquals("Fail with seed:" + seed, compatibleSet, testSet);
assertEquals("Fail with seed:" + seed, compatibleSet.hashCode(), testSet.hashCode());
}

private static void addTwoElements(final IntHashSet obj)
{
obj.add(1);
obj.add(1001);
}

private static void addTwoElements(final HashSet<Integer> obj)
{
obj.add(1);
obj.add(1001);
}

private void assertIteratorHasElements()
{
final Iterator<Integer> iter = testSet.iterator();

final Set<Integer> values = new HashSet<>();

assertTrue(iter.hasNext());
values.add(iter.next());
assertTrue(iter.hasNext());
values.add(iter.next());
assertFalse(iter.hasNext());

assertContainsElements(values);
}

private void assertIteratorHasElementsWithoutHasNext()
{
final Iterator<Integer> iter = testSet.iterator();

final Set<Integer> values = new HashSet<>();

values.add(iter.next());
values.add(iter.next());

assertContainsElements(values);
}

private static void assertArrayContainingElements(final Integer[] result)
{
assertThat(result, arrayContainingInAnyOrder(1, 1001));
}

private static void assertContainsElements(final Set<Integer> other)
{
assertThat(other, containsInAnyOrder(1, 1001));
}

private void exhaustIterator()
{
final IntIterator iterator = testSet.iterator();
iterator.next();
iterator.next();
iterator.next();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,24 @@ public void shouldIterateOverExpandedSet()
assertFalse(iter.hasNext());
}

@Test
public void shouldHaveCompatibleEqualsAndHashcode()
{
final HashSet compatibleSet = new HashSet();
final long seed = System.nanoTime();
final Random r = new Random(seed);
for (int i = 0; i < 1024; i++)
{
final int value = r.nextInt();
compatibleSet.add(value);
testSet.add(value);
}

assertEquals("Fail with seed:" + seed, testSet, compatibleSet);
assertEquals("Fail with seed:" + seed, compatibleSet, testSet);
assertEquals("Fail with seed:" + seed, compatibleSet.hashCode(), testSet.hashCode());
}

private static void addTwoElements(final ObjectHashSet<Integer> obj)
{
obj.add(1);
Expand Down

0 comments on commit 34d25cc

Please sign in to comment.