@Test public void serialization() { int size = COLLISIONS.size(); for (int i = 1; i < size; i++) { MutableSet<Integer> set = UnifiedSetWithHashingStrategy.newSet(INTEGER_HASHING_STRATEGY, SIZE) .withAll(COLLISIONS.subList(0, i)); Verify.assertPostSerializedEqualsAndHashCode(set); set.add(null); Verify.assertPostSerializedEqualsAndHashCode(set); } UnifiedSetWithHashingStrategy<Integer> nullBucketZero = UnifiedSetWithHashingStrategy.newSetWith( INTEGER_HASHING_STRATEGY, null, COLLISION_1, COLLISION_2); Verify.assertPostSerializedEqualsAndHashCode(nullBucketZero); UnifiedSetWithHashingStrategy<Integer> simpleSetWithNull = UnifiedSetWithHashingStrategy.newSetWith(INTEGER_HASHING_STRATEGY, null, 1, 2); Verify.assertPostSerializedEqualsAndHashCode(simpleSetWithNull); UnifiedSetWithHashingStrategy<Person> people = UnifiedSetWithHashingStrategy.newSet(LAST_NAME_HASHING_STRATEGY, PEOPLE); Verify.assertPostSerializedEqualsAndHashCode(people); // Testing the hashingStrategy is serialized correctly by making sure it is still hashing by // last name Verify.assertSetsEqual(LAST_NAME_HASHED_SET.castToSet(), people.withAll(PEOPLE.castToList())); }
@Test public void put() { int size = MORE_COLLISIONS.size(); for (int i = 1; i <= size; i++) { Pool<Integer> unifiedSet = UnifiedSetWithHashingStrategy.newSet(INTEGER_HASHING_STRATEGY, 1) .withAll(MORE_COLLISIONS.subList(0, i - 1)); Integer newValue = MORE_COLLISIONS.get(i - 1); Assert.assertSame(newValue, unifiedSet.put(newValue)); //noinspection UnnecessaryBoxing,CachedNumberConstructorCall,BoxingBoxedValue Assert.assertSame(newValue, unifiedSet.put(new Integer(newValue))); } // assert that all redundant puts into a each position of chain bucket return the original // element added Pool<Integer> set = UnifiedSetWithHashingStrategy.newSet(INTEGER_HASHING_STRATEGY, 4) .with(COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4); for (int i = 0; i < set.size(); i++) { Integer value = COLLISIONS.get(i); Assert.assertSame(value, set.put(value)); } // force rehashing at each step of putting a new colliding entry for (int i = 0; i < COLLISIONS.size(); i++) { Pool<Integer> pool = UnifiedSetWithHashingStrategy.newSet(INTEGER_HASHING_STRATEGY, i) .withAll(COLLISIONS.subList(0, i)); if (i == 2) { pool.put(Integer.valueOf(1)); } if (i == 4) { pool.put(Integer.valueOf(1)); pool.put(Integer.valueOf(2)); } Integer value = COLLISIONS.get(i); Assert.assertSame(value, pool.put(value)); } // cover one case not covered in the above: a bucket with only one entry and a low capacity // forcing a rehash // set up a chained bucket Pool<Integer> pool = UnifiedSetWithHashingStrategy.newSet(INTEGER_HASHING_STRATEGY, 2) .with(COLLISION_1, COLLISION_2); // clear the bucket to one element pool.removeFromPool(COLLISION_2); // increase the occupied count to the threshold pool.put(Integer.valueOf(1)); pool.put(Integer.valueOf(2)); // put the colliding value back and force the rehash Assert.assertSame(COLLISION_2, pool.put(COLLISION_2)); // put chained items into a pool without causing a rehash Pool<Integer> olympicPool = UnifiedSetWithHashingStrategy.newSet(INTEGER_HASHING_STRATEGY); Assert.assertSame(COLLISION_1, olympicPool.put(COLLISION_1)); Assert.assertSame(COLLISION_2, olympicPool.put(COLLISION_2)); }
@Test public void removeFromPool() { Pool<Integer> unifiedSet = UnifiedSetWithHashingStrategy.newSet(INTEGER_HASHING_STRATEGY, 8).withAll(COLLISIONS); COLLISIONS.reverseForEach( each -> { Assert.assertNull(unifiedSet.removeFromPool(null)); Assert.assertSame(each, unifiedSet.removeFromPool(each)); Assert.assertNull(unifiedSet.removeFromPool(each)); Assert.assertNull(unifiedSet.removeFromPool(null)); Assert.assertNull(unifiedSet.removeFromPool(COLLISION_10)); }); Assert.assertEquals(UnifiedSetWithHashingStrategy.newSet(INTEGER_HASHING_STRATEGY), unifiedSet); COLLISIONS.forEach( Procedures.cast( each -> { Pool<Integer> unifiedSet2 = UnifiedSetWithHashingStrategy.newSet(INTEGER_HASHING_STRATEGY, 8) .withAll(COLLISIONS); Assert.assertNull(unifiedSet2.removeFromPool(null)); Assert.assertSame(each, unifiedSet2.removeFromPool(each)); Assert.assertNull(unifiedSet2.removeFromPool(each)); Assert.assertNull(unifiedSet2.removeFromPool(null)); Assert.assertNull(unifiedSet2.removeFromPool(COLLISION_10)); })); // search a chain for a non-existent element Pool<Integer> chain = UnifiedSetWithHashingStrategy.newSetWith( INTEGER_HASHING_STRATEGY, COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4); Assert.assertNull(chain.removeFromPool(COLLISION_5)); // search a deep chain for a non-existent element Pool<Integer> deepChain = UnifiedSetWithHashingStrategy.newSetWith( INTEGER_HASHING_STRATEGY, COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4, COLLISION_5, COLLISION_6, COLLISION_7); Assert.assertNull(deepChain.removeFromPool(COLLISION_8)); // search for a non-existent element Pool<Integer> empty = UnifiedSetWithHashingStrategy.newSetWith(INTEGER_HASHING_STRATEGY, COLLISION_1); Assert.assertNull(empty.removeFromPool(COLLISION_2)); }
@Override @Test public void toArray() { super.toArray(); int size = COLLISIONS.size(); for (int i = 1; i < size; i++) { MutableSet<Integer> set = UnifiedSetWithHashingStrategy.newSet(INTEGER_HASHING_STRATEGY, SIZE) .withAll(COLLISIONS.subList(0, i)); Object[] objects = set.toArray(); Assert.assertEquals(set, UnifiedSet.newSetWith(objects)); } MutableSet<Integer> deepChain = UnifiedSetWithHashingStrategy.newSetWith( INTEGER_HASHING_STRATEGY, COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4, COLLISION_5, COLLISION_6); Assert.assertArrayEquals( new Integer[] { COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4, COLLISION_5, COLLISION_6 }, deepChain.toArray()); MutableSet<Integer> minimumChain = UnifiedSetWithHashingStrategy.newSetWith( INTEGER_HASHING_STRATEGY, COLLISION_1, COLLISION_2); minimumChain.remove(COLLISION_2); Assert.assertArrayEquals(new Integer[] {COLLISION_1}, minimumChain.toArray()); MutableSet<Integer> set = UnifiedSetWithHashingStrategy.newSetWith( INTEGER_HASHING_STRATEGY, COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4); Integer[] target = { Integer.valueOf(1), Integer.valueOf(1), Integer.valueOf(1), Integer.valueOf(1), Integer.valueOf(1), Integer.valueOf(1) }; Integer[] actual = set.toArray(target); ArrayIterate.sort(actual, actual.length, Comparators.safeNullsHigh(Integer::compareTo)); Assert.assertArrayEquals( new Integer[] {COLLISION_1, 1, COLLISION_2, COLLISION_3, COLLISION_4, null}, actual); }
@Override @Test public void add() { super.add(); // force rehashing at each step of adding a new colliding entry for (int i = 0; i < COLLISIONS.size(); i++) { UnifiedSetWithHashingStrategy<Integer> unifiedSet = UnifiedSetWithHashingStrategy.newSet(INTEGER_HASHING_STRATEGY, i, 0.75f) .withAll(COLLISIONS.subList(0, i)); if (i == 2) { unifiedSet.add(Integer.valueOf(1)); } if (i == 4) { unifiedSet.add(Integer.valueOf(1)); unifiedSet.add(Integer.valueOf(2)); } Integer value = COLLISIONS.get(i); Assert.assertTrue(unifiedSet.add(value)); } // Rehashing Case A: a bucket with only one entry and a low capacity forcing a rehash, where the // trigging element goes in the bucket // set up a chained bucket UnifiedSetWithHashingStrategy<Integer> caseA = UnifiedSetWithHashingStrategy.newSet(INTEGER_HASHING_STRATEGY, 2) .with(COLLISION_1, COLLISION_2); // clear the bucket to one element caseA.remove(COLLISION_2); // increase the occupied count to the threshold caseA.add(Integer.valueOf(1)); caseA.add(Integer.valueOf(2)); // add the colliding value back and force the rehash Assert.assertTrue(caseA.add(COLLISION_2)); // Rehashing Case B: a bucket with only one entry and a low capacity forcing a rehash, where the // triggering element is not in the chain // set up a chained bucket UnifiedSetWithHashingStrategy<Integer> caseB = UnifiedSetWithHashingStrategy.newSet(INTEGER_HASHING_STRATEGY, 2) .with(COLLISION_1, COLLISION_2); // clear the bucket to one element caseB.remove(COLLISION_2); // increase the occupied count to the threshold caseB.add(Integer.valueOf(1)); caseB.add(Integer.valueOf(2)); // add a new value and force the rehash Assert.assertTrue(caseB.add(3)); }
@Test public void get() { UnifiedSetWithHashingStrategy<Integer> set = UnifiedSetWithHashingStrategy.newSet(INTEGER_HASHING_STRATEGY, SIZE).withAll(COLLISIONS); set.removeAll(COLLISIONS); for (Integer integer : COLLISIONS) { Assert.assertNull(set.get(integer)); Assert.assertNull(set.get(null)); set.add(integer); //noinspection UnnecessaryBoxing,CachedNumberConstructorCall,BoxingBoxedValue Assert.assertSame(integer, set.get(new Integer(integer))); } Assert.assertEquals(COLLISIONS.toSet(), set); // the pool interface supports getting null keys UnifiedSetWithHashingStrategy<Integer> chainedWithNull = UnifiedSetWithHashingStrategy.newSetWith(INTEGER_HASHING_STRATEGY, null, COLLISION_1); Verify.assertContains(null, chainedWithNull); Assert.assertNull(chainedWithNull.get(null)); // getting a non-existent from a chain with one slot should short-circuit to return null UnifiedSetWithHashingStrategy<Integer> chainedWithOneSlot = UnifiedSetWithHashingStrategy.newSetWith( INTEGER_HASHING_STRATEGY, COLLISION_1, COLLISION_2); chainedWithOneSlot.remove(COLLISION_2); Assert.assertNull(chainedWithOneSlot.get(COLLISION_2)); }