/*
* Copyright 2015 Goldman Sachs.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gs.collections.impl.set.mutable;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.Executors;
import com.gs.collections.api.set.MutableSet;
import com.gs.collections.api.set.Pool;
import com.gs.collections.impl.block.factory.Comparators;
import com.gs.collections.impl.block.factory.Procedures;
import com.gs.collections.impl.factory.Lists;
import com.gs.collections.impl.factory.Sets;
import com.gs.collections.impl.list.Interval;
import com.gs.collections.impl.list.mutable.FastList;
import com.gs.collections.impl.math.IntegerSum;
import com.gs.collections.impl.math.Sum;
import com.gs.collections.impl.math.SumProcedure;
import com.gs.collections.impl.test.Verify;
import com.gs.collections.impl.test.domain.Key;
import com.gs.collections.impl.utility.ArrayIterate;
import org.junit.Assert;
import org.junit.Test;
/**
* JUnit test suite for {@link UnifiedSet}.
*/
public class UnifiedSetTest extends AbstractMutableSetTestCase
{
@Override
protected <T> UnifiedSet<T> newWith(T... littleElements)
{
return UnifiedSet.newSetWith(littleElements);
}
@Override
@Test
public void with()
{
Verify.assertEqualsAndHashCode(
UnifiedSet.newSetWith("1"),
UnifiedSet.newSet().with("1"));
Verify.assertEqualsAndHashCode(
UnifiedSet.newSetWith("1", "2"),
UnifiedSet.newSet().with("1", "2"));
Verify.assertEqualsAndHashCode(
UnifiedSet.newSetWith("1", "2", "3"),
UnifiedSet.newSet().with("1", "2", "3"));
Verify.assertEqualsAndHashCode(
UnifiedSet.newSetWith("1", "2", "3", "4"),
UnifiedSet.newSet().with("1", "2", "3", "4"));
MutableSet<String> list = UnifiedSet.<String>newSet().with("A")
.withAll(Lists.fixedSize.of("1", "2"))
.withAll(Lists.fixedSize.<String>of())
.withAll(Sets.fixedSize.of("3", "4"));
Verify.assertEqualsAndHashCode(UnifiedSet.newSetWith("A", "1", "2", "3", "4"), list);
}
@Test
public void newSet_throws()
{
Verify.assertThrows(IllegalArgumentException.class, () -> new UnifiedSet<Integer>(-1, 0.5f));
Verify.assertThrows(IllegalArgumentException.class, () -> new UnifiedSet<Integer>(1, -0.5f));
Verify.assertThrows(IllegalArgumentException.class, () -> new UnifiedSet<Integer>(1, 0.0f));
Verify.assertThrows(IllegalArgumentException.class, () -> new UnifiedSet<Integer>(1, 1.5f));
}
@Test
public void newSetWithIterable()
{
MutableSet<Integer> integers = UnifiedSet.newSet(Interval.oneTo(3));
Assert.assertEquals(UnifiedSet.newSetWith(1, 2, 3), integers);
}
@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++)
{
UnifiedSet<Integer> unifiedSet = UnifiedSet.<Integer>newSet(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
UnifiedSet<Integer> caseA = UnifiedSet.<Integer>newSet(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
UnifiedSet<Integer> caseB = UnifiedSet.<Integer>newSet(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));
}
@Override
@Test
public void addAllIterable()
{
super.addAllIterable();
// test adding a fully populated chained bucket
MutableSet<Integer> expected = UnifiedSet.newSetWith(COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4, COLLISION_5, COLLISION_6, COLLISION_7);
Assert.assertTrue(UnifiedSet.<Integer>newSet().addAllIterable(expected));
// add an odd-sized collection to a set with a small max to ensure that its capacity is maintained after the operation.
UnifiedSet<Integer> tiny = UnifiedSet.newSet(0);
Assert.assertTrue(tiny.addAllIterable(FastList.newListWith(COLLISION_1)));
}
@Test
public void get()
{
UnifiedSet<Integer> set = UnifiedSet.<Integer>newSet(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
UnifiedSet<Integer> chainedWithNull = UnifiedSet.newSetWith(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
UnifiedSet<Integer> chainedWithOneSlot = UnifiedSet.newSetWith(COLLISION_1, COLLISION_2);
chainedWithOneSlot.remove(COLLISION_2);
Assert.assertNull(chainedWithOneSlot.get(COLLISION_2));
}
@Test
public void put()
{
int size = MORE_COLLISIONS.size();
for (int i = 1; i <= size; i++)
{
Pool<Integer> unifiedSet = UnifiedSet.<Integer>newSet(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 = UnifiedSet.<Integer>newSet(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 = UnifiedSet.<Integer>newSet(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 = UnifiedSet.<Integer>newSet(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 = UnifiedSet.newSet();
Assert.assertSame(COLLISION_1, olympicPool.put(COLLISION_1));
Assert.assertSame(COLLISION_2, olympicPool.put(COLLISION_2));
}
@Test
public void removeFromPool()
{
Pool<Integer> unifiedSet = UnifiedSet.<Integer>newSet(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(UnifiedSet.<Integer>newSet(), unifiedSet);
COLLISIONS.forEach(Procedures.cast(each -> {
Pool<Integer> unifiedSet2 = UnifiedSet.<Integer>newSet(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 = UnifiedSet.newSetWith(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 = UnifiedSet.newSetWith(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 = UnifiedSet.newSetWith(COLLISION_1);
Assert.assertNull(empty.removeFromPool(COLLISION_2));
}
@Test
public void serialization()
{
int size = COLLISIONS.size();
for (int i = 1; i < size; i++)
{
MutableSet<Integer> set = UnifiedSet.<Integer>newSet(SIZE).withAll(COLLISIONS.subList(0, i));
Verify.assertPostSerializedEqualsAndHashCode(set);
set.add(null);
Verify.assertPostSerializedEqualsAndHashCode(set);
}
UnifiedSet<Integer> nullBucketZero = UnifiedSet.newSetWith(null, COLLISION_1, COLLISION_2);
Verify.assertPostSerializedEqualsAndHashCode(nullBucketZero);
UnifiedSet<Integer> simpleSetWithNull = UnifiedSet.newSetWith(null, 1, 2);
Verify.assertPostSerializedEqualsAndHashCode(simpleSetWithNull);
}
@Test
public void null_behavior()
{
UnifiedSet<Integer> unifiedSet = UnifiedSet.<Integer>newSet(10).withAll(MORE_COLLISIONS);
MORE_COLLISIONS.clone().reverseForEach(each -> {
Assert.assertTrue(unifiedSet.add(null));
Assert.assertFalse(unifiedSet.add(null));
Verify.assertContains(null, unifiedSet);
Verify.assertPostSerializedEqualsAndHashCode(unifiedSet);
Assert.assertTrue(unifiedSet.remove(null));
Assert.assertFalse(unifiedSet.remove(null));
Verify.assertNotContains(null, unifiedSet);
Verify.assertPostSerializedEqualsAndHashCode(unifiedSet);
Assert.assertNull(unifiedSet.put(null));
Assert.assertNull(unifiedSet.put(null));
Assert.assertNull(unifiedSet.removeFromPool(null));
Assert.assertNull(unifiedSet.removeFromPool(null));
Verify.assertContains(each, unifiedSet);
Assert.assertTrue(unifiedSet.remove(each));
Assert.assertFalse(unifiedSet.remove(each));
Verify.assertNotContains(each, unifiedSet);
});
}
@Override
@Test
public void equalsAndHashCode()
{
super.equalsAndHashCode();
UnifiedSet<Integer> singleCollisionBucket = UnifiedSet.newSetWith(COLLISION_1, COLLISION_2);
singleCollisionBucket.remove(COLLISION_2);
Assert.assertEquals(singleCollisionBucket, UnifiedSet.newSetWith(COLLISION_1));
Verify.assertEqualsAndHashCode(UnifiedSet.newSetWith(null, COLLISION_1, COLLISION_2, COLLISION_3), UnifiedSet.newSetWith(null, COLLISION_1, COLLISION_2, COLLISION_3));
Verify.assertEqualsAndHashCode(UnifiedSet.newSetWith(COLLISION_1, null, COLLISION_2, COLLISION_3), UnifiedSet.newSetWith(COLLISION_1, null, COLLISION_2, COLLISION_3));
Verify.assertEqualsAndHashCode(UnifiedSet.newSetWith(COLLISION_1, COLLISION_2, null, COLLISION_3), UnifiedSet.newSetWith(COLLISION_1, COLLISION_2, null, COLLISION_3));
Verify.assertEqualsAndHashCode(UnifiedSet.newSetWith(COLLISION_1, COLLISION_2, COLLISION_3, null), UnifiedSet.newSetWith(COLLISION_1, COLLISION_2, COLLISION_3, null));
}
@Test
public void constructor_from_UnifiedSet()
{
Verify.assertEqualsAndHashCode(new HashSet<>(MORE_COLLISIONS), UnifiedSet.newSet(MORE_COLLISIONS));
}
@Test
public void copyConstructor()
{
// test copying a chained bucket
MutableSet<Integer> set = UnifiedSet.newSetWith(COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4, COLLISION_5, COLLISION_6, COLLISION_7);
Verify.assertEqualsAndHashCode(set, UnifiedSet.newSet(set));
}
@Test
public void newSet()
{
for (int i = 1; i < 17; i++)
{
this.assertPresizedSet(i, 0.75f);
}
this.assertPresizedSet(31, 0.75f);
this.assertPresizedSet(32, 0.75f);
this.assertPresizedSet(34, 0.75f);
this.assertPresizedSet(60, 0.75f);
this.assertPresizedSet(64, 0.70f);
this.assertPresizedSet(68, 0.70f);
this.assertPresizedSet(60, 0.70f);
this.assertPresizedSet(1025, 0.80f);
this.assertPresizedSet(1024, 0.80f);
this.assertPresizedSet(1025, 0.80f);
this.assertPresizedSet(1024, 0.805f);
}
private void assertPresizedSet(int initialCapacity, float loadFactor)
{
try
{
Field tableField = UnifiedSet.class.getDeclaredField("table");
tableField.setAccessible(true);
Object[] table = (Object[]) tableField.get(UnifiedSet.newSet(initialCapacity, loadFactor));
int size = (int) Math.ceil(initialCapacity / loadFactor);
int capacity = 1;
while (capacity < size)
{
capacity <<= 1;
}
Assert.assertEquals(capacity, table.length, 0.00);
}
catch (SecurityException ignored)
{
Assert.fail("Unable to modify the visibility of the table on UnifiedSet");
}
catch (NoSuchFieldException ignored)
{
Assert.fail("No field named table UnifiedSet");
}
catch (IllegalAccessException ignored)
{
Assert.fail("No access the field table in UnifiedSet");
}
}
@Test
public void batchForEach()
{
//Testing batch size of 1 to 16 with no chains
UnifiedSet<Integer> set = UnifiedSet.<Integer>newSet(10).with(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
for (int sectionCount = 1; sectionCount <= 16; ++sectionCount)
{
Sum sum = new IntegerSum(0);
for (int sectionIndex = 0; sectionIndex < sectionCount; ++sectionIndex)
{
set.batchForEach(new SumProcedure<>(sum), sectionIndex, sectionCount);
}
Assert.assertEquals(55, sum.getValue());
}
//Testing 1 batch with chains
Sum sum2 = new IntegerSum(0);
UnifiedSet<Integer> set2 = UnifiedSet.<Integer>newSet(3).with(COLLISION_1, COLLISION_2, COLLISION_3, 1, 2);
int numBatches = set2.getBatchCount(100);
for (int i = 0; i < numBatches; ++i)
{
set2.batchForEach(new SumProcedure<>(sum2), i, numBatches);
}
Assert.assertEquals(1, numBatches);
Assert.assertEquals(54, sum2.getValue());
//Testing batch size of 3 with chains and uneven last batch
Sum sum3 = new IntegerSum(0);
UnifiedSet<Integer> set3 = UnifiedSet.<Integer>newSet(4, 1.0F).with(COLLISION_1, COLLISION_2, 1, 2, 3, 4, 5);
int numBatches2 = set3.getBatchCount(3);
for (int i = 0; i < numBatches2; ++i)
{
set3.batchForEach(new SumProcedure<>(sum3), i, numBatches2);
}
Assert.assertEquals(32, sum3.getValue());
//Test batchForEach on empty set, it should simply do nothing and not throw any exceptions
Sum sum4 = new IntegerSum(0);
UnifiedSet<Integer> set4 = UnifiedSet.newSet();
set4.batchForEach(new SumProcedure<>(sum4), 0, set4.getBatchCount(1));
Assert.assertEquals(0, sum4.getValue());
}
@Override
@Test
public void toArray()
{
super.toArray();
int size = COLLISIONS.size();
for (int i = 1; i < size; i++)
{
MutableSet<Integer> set = UnifiedSet.<Integer>newSet(SIZE).withAll(COLLISIONS.subList(0, i));
Object[] objects = set.toArray();
Assert.assertEquals(set, UnifiedSet.newSetWith(objects));
}
MutableSet<Integer> deepChain = UnifiedSet.newSetWith(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 = UnifiedSet.newSetWith(COLLISION_1, COLLISION_2);
minimumChain.remove(COLLISION_2);
Assert.assertArrayEquals(new Integer[]{COLLISION_1}, minimumChain.toArray());
MutableSet<Integer> set = UnifiedSet.newSetWith(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);
}
@Test
public void iterator_remove()
{
int size = MORE_COLLISIONS.size();
for (int i = 0; i < size; i++)
{
MutableSet<Integer> actual = UnifiedSet.<Integer>newSet(SIZE).withAll(MORE_COLLISIONS);
Iterator<Integer> iterator = actual.iterator();
for (int j = 0; j <= i; j++)
{
Assert.assertTrue(iterator.hasNext());
iterator.next();
}
iterator.remove();
MutableSet<Integer> expected = UnifiedSet.newSet(MORE_COLLISIONS);
expected.remove(MORE_COLLISIONS.get(i));
Assert.assertEquals(expected, actual);
}
// remove the last element from within a 2-level long chain that is fully populated
MutableSet<Integer> set = UnifiedSet.newSetWith(COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4, COLLISION_5, COLLISION_6, COLLISION_7);
Iterator<Integer> iterator1 = set.iterator();
for (int i = 0; i < 7; i++)
{
iterator1.next();
}
iterator1.remove();
Assert.assertEquals(UnifiedSet.newSetWith(COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4, COLLISION_5, COLLISION_6), set);
// remove the second-to-last element from a 2-level long chain that that has one empty slot
Iterator<Integer> iterator2 = set.iterator();
for (int i = 0; i < 6; i++)
{
iterator2.next();
}
iterator2.remove();
Assert.assertEquals(UnifiedSet.newSetWith(COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4, COLLISION_5), set);
//Testing removing the last element in a fully populated chained bucket
MutableSet<Integer> set2 = this.newWith(COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4);
Iterator<Integer> iterator3 = set2.iterator();
for (int i = 0; i < 3; ++i)
{
iterator3.next();
}
iterator3.next();
iterator3.remove();
Verify.assertSetsEqual(UnifiedSet.newSetWith(COLLISION_1, COLLISION_2, COLLISION_3), set2);
}
@Test
public void setKeyPreservation()
{
Key key = new Key("key");
Key duplicateKey1 = new Key("key");
MutableSet<Key> set1 = UnifiedSet.<Key>newSet().with(key, duplicateKey1);
Verify.assertSize(1, set1);
Verify.assertContains(key, set1);
Assert.assertSame(key, set1.getFirst());
Key duplicateKey2 = new Key("key");
MutableSet<Key> set2 = UnifiedSet.<Key>newSet().with(key, duplicateKey1, duplicateKey2);
Verify.assertSize(1, set2);
Verify.assertContains(key, set2);
Assert.assertSame(key, set2.getFirst());
Key duplicateKey3 = new Key("key");
MutableSet<Key> set3 = UnifiedSet.<Key>newSet().with(key, new Key("not a dupe"), duplicateKey3);
Verify.assertSize(2, set3);
Verify.assertContainsAll(set3, key, new Key("not a dupe"));
Assert.assertSame(key, set3.detect(key::equals));
}
@Test
public void withSameIfNotModified()
{
UnifiedSet<Integer> integers = UnifiedSet.newSet();
Assert.assertEquals(UnifiedSet.newSetWith(1, 2), integers.with(1, 2));
Assert.assertEquals(UnifiedSet.newSetWith(1, 2, 3, 4), integers.with(2, 3, 4));
Assert.assertSame(integers, integers.with(5, 6, 7));
}
@Override
@Test
public void retainAll()
{
super.retainAll();
MutableSet<Object> setWithNull = this.newWith((Object) null);
Assert.assertFalse(setWithNull.retainAll(FastList.newListWith((Object) null)));
Assert.assertEquals(UnifiedSet.newSetWith((Object) null), setWithNull);
}
@Test(expected = NullPointerException.class)
public void asParallelNullExecutorService()
{
this.newWith(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).asParallel(null, 2);
}
@Test(expected = IllegalArgumentException.class)
public void asParallelLessThanOneBatchSize()
{
this.newWith(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).asParallel(Executors.newFixedThreadPool(10), 0);
}
@Override
public void getFirst()
{
super.getFirst();
int size = MORE_COLLISIONS.size();
for (int i = 1; i <= size - 1; i++)
{
MutableSet<Integer> unifiedSet = UnifiedSet.<Integer>newSet(1).withAll(MORE_COLLISIONS.subList(0, i));
Assert.assertSame(MORE_COLLISIONS.get(0), unifiedSet.getFirst());
}
}
@Override
public void getLast()
{
super.getLast();
int size = MORE_COLLISIONS.size();
for (int i = 1; i <= size - 1; i++)
{
MutableSet<Integer> unifiedSet = UnifiedSet.<Integer>newSet(1).withAll(MORE_COLLISIONS.subList(0, i));
Assert.assertSame(MORE_COLLISIONS.get(i - 1), unifiedSet.getLast());
}
MutableSet<Integer> chainedWithOneSlot = UnifiedSet.newSetWith(COLLISION_1, COLLISION_2);
chainedWithOneSlot.remove(COLLISION_2);
Assert.assertSame(COLLISION_1, chainedWithOneSlot.getLast());
}
}