2
* Copyright 2014 Goldman Sachs.
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
17
package com.gs.collections.impl.set.mutable;
19
import java.util.Arrays;
20
import java.util.Iterator;
21
import java.util.NoSuchElementException;
23
import com.gs.collections.api.LazyIterable;
24
import com.gs.collections.api.block.function.Function;
25
import com.gs.collections.api.list.MutableList;
26
import com.gs.collections.api.set.MutableSet;
27
import com.gs.collections.api.set.UnsortedSetIterable;
28
import com.gs.collections.api.tuple.Pair;
29
import com.gs.collections.impl.Counter;
30
import com.gs.collections.impl.IntegerWithCast;
31
import com.gs.collections.impl.block.factory.Predicates;
32
import com.gs.collections.impl.block.factory.Procedures;
33
import com.gs.collections.impl.block.procedure.CollectionAddProcedure;
34
import com.gs.collections.impl.collection.mutable.AbstractCollectionTestCase;
35
import com.gs.collections.impl.factory.Lists;
36
import com.gs.collections.impl.list.Interval;
37
import com.gs.collections.impl.list.mutable.FastList;
38
import com.gs.collections.impl.test.Verify;
39
import com.gs.collections.impl.utility.Iterate;
40
import org.junit.Assert;
41
import org.junit.Test;
43
import static com.gs.collections.impl.factory.Iterables.*;
46
* JUnit test for {@link AbstractMutableSet}.
48
public abstract class AbstractMutableSetTestCase extends AbstractCollectionTestCase
50
protected static final Integer COLLISION_1 = 0;
51
protected static final Integer COLLISION_2 = 17;
52
protected static final Integer COLLISION_3 = 34;
53
protected static final Integer COLLISION_4 = 51;
54
protected static final Integer COLLISION_5 = 68;
55
protected static final Integer COLLISION_6 = 85;
56
protected static final Integer COLLISION_7 = 102;
57
protected static final Integer COLLISION_8 = 119;
58
protected static final Integer COLLISION_9 = 136;
59
protected static final Integer COLLISION_10 = 152;
60
protected static final MutableList<Integer> COLLISIONS =
61
FastList.newListWith(COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4, COLLISION_5);
62
protected static final MutableList<Integer> MORE_COLLISIONS = FastList.newList(COLLISIONS)
63
.with(COLLISION_6, COLLISION_7, COLLISION_8, COLLISION_9);
64
protected static final int SIZE = 8;
66
protected abstract <T> MutableSet<T> newWith(T... littleElements);
70
public void asSynchronized()
72
Verify.assertInstanceOf(SynchronizedMutableSet.class, this.newWith().asSynchronized());
81
UnifiedSet<Integer> expected = UnifiedSet.newSetWith(1, 2, 3);
82
MutableSet<Integer> collection = this.newWith();
84
Assert.assertTrue(collection.addAll(FastList.newListWith(1, 2, 3)));
85
Assert.assertEquals(expected, collection);
87
Assert.assertFalse(collection.addAll(FastList.newListWith(1, 2, 3)));
88
Assert.assertEquals(expected, collection);
93
public void addAllIterable()
95
super.addAllIterable();
97
UnifiedSet<Integer> expected = UnifiedSet.newSetWith(1, 2, 3);
98
MutableSet<Integer> collection = this.newWith();
100
Assert.assertTrue(collection.addAllIterable(FastList.newListWith(1, 2, 3)));
101
Assert.assertEquals(expected, collection);
103
Assert.assertFalse(collection.addAllIterable(FastList.newListWith(1, 2, 3)));
104
Assert.assertEquals(expected, collection);
110
MutableSet<String> set = this.newWith("1", "2", "3", "4");
111
MutableSet<String> union = set.union(UnifiedSet.newSetWith("a", "b", "c", "1"));
112
Verify.assertSize(set.size() + 3, union);
113
Assert.assertTrue(union.containsAllIterable(Interval.oneTo(set.size()).collect(String::valueOf)));
114
Verify.assertContainsAll(union, "a", "b", "c");
116
Assert.assertEquals(set, set.union(UnifiedSet.newSetWith("1")));
120
public void unionInto()
122
MutableSet<String> set = this.newWith("1", "2", "3", "4");
123
MutableSet<String> union = set.unionInto(UnifiedSet.newSetWith("a", "b", "c", "1"), UnifiedSet.<String>newSet());
124
Verify.assertSize(set.size() + 3, union);
125
Assert.assertTrue(union.containsAllIterable(Interval.oneTo(set.size()).collect(String::valueOf)));
126
Verify.assertContainsAll(union, "a", "b", "c");
128
Assert.assertEquals(set, set.unionInto(UnifiedSet.newSetWith("1"), UnifiedSet.<String>newSet()));
132
public void intersect()
134
MutableSet<String> set = this.newWith("1", "2", "3", "4");
135
MutableSet<String> intersect = set.intersect(UnifiedSet.newSetWith("a", "b", "c", "1"));
136
Verify.assertSize(1, intersect);
137
Assert.assertEquals(UnifiedSet.newSetWith("1"), intersect);
139
Verify.assertEmpty(set.intersect(UnifiedSet.newSetWith("not present")));
143
public void intersectInto()
145
MutableSet<String> set = this.newWith("1", "2", "3", "4");
146
MutableSet<String> intersect = set.intersectInto(UnifiedSet.newSetWith("a", "b", "c", "1"), UnifiedSet.<String>newSet());
147
Verify.assertSize(1, intersect);
148
Assert.assertEquals(UnifiedSet.newSetWith("1"), intersect);
150
Verify.assertEmpty(set.intersectInto(UnifiedSet.newSetWith("not present"), UnifiedSet.<String>newSet()));
154
public void difference()
156
MutableSet<String> set = this.newWith("1", "2", "3", "4");
157
MutableSet<String> difference = set.difference(UnifiedSet.newSetWith("2", "3", "4", "not present"));
158
Assert.assertEquals(UnifiedSet.newSetWith("1"), difference);
159
Assert.assertEquals(set, set.difference(UnifiedSet.newSetWith("not present")));
163
public void differenceInto()
165
MutableSet<String> set = this.newWith("1", "2", "3", "4");
166
MutableSet<String> difference = set.differenceInto(UnifiedSet.newSetWith("2", "3", "4", "not present"), UnifiedSet.<String>newSet());
167
Assert.assertEquals(UnifiedSet.newSetWith("1"), difference);
168
Assert.assertEquals(set, set.differenceInto(UnifiedSet.newSetWith("not present"), UnifiedSet.<String>newSet()));
172
public void symmetricDifference()
174
MutableSet<String> set = this.newWith("1", "2", "3", "4");
175
MutableSet<String> difference = set.symmetricDifference(UnifiedSet.newSetWith("2", "3", "4", "5", "not present"));
176
Verify.assertContains("1", difference);
177
Assert.assertTrue(difference.containsAllIterable(Interval.fromTo(set.size() + 1, 5).collect(String::valueOf)));
178
for (int i = 2; i <= set.size(); i++)
180
Verify.assertNotContains(String.valueOf(i), difference);
183
Verify.assertSize(set.size() + 1, set.symmetricDifference(UnifiedSet.newSetWith("not present")));
187
public void symmetricDifferenceInto()
189
MutableSet<String> set = this.newWith("1", "2", "3", "4");
190
MutableSet<String> difference = set.symmetricDifferenceInto(
191
UnifiedSet.newSetWith("2", "3", "4", "5", "not present"),
192
UnifiedSet.<String>newSet());
193
Verify.assertContains("1", difference);
194
Assert.assertTrue(difference.containsAllIterable(Interval.fromTo(set.size() + 1, 5).collect(String::valueOf)));
195
for (int i = 2; i <= set.size(); i++)
197
Verify.assertNotContains(String.valueOf(i), difference);
202
set.symmetricDifferenceInto(UnifiedSet.newSetWith("not present"), UnifiedSet.<String>newSet()));
206
public void isSubsetOf()
208
MutableSet<String> set = this.newWith("1", "2", "3", "4");
209
Assert.assertTrue(set.isSubsetOf(UnifiedSet.newSetWith("1", "2", "3", "4", "5")));
213
public void isProperSubsetOf()
215
MutableSet<String> set = this.newWith("1", "2", "3", "4");
216
Assert.assertTrue(set.isProperSubsetOf(UnifiedSet.newSetWith("1", "2", "3", "4", "5")));
217
Assert.assertFalse(set.isProperSubsetOf(set));
221
public void powerSet()
223
MutableSet<String> set = this.newWith("1", "2", "3", "4");
224
MutableSet<UnsortedSetIterable<String>> powerSet = set.powerSet();
225
Verify.assertSize((int) StrictMath.pow(2, set.size()), powerSet);
226
Verify.assertContains(UnifiedSet.<String>newSet(), powerSet);
227
Verify.assertContains(set, powerSet);
231
public void cartesianProduct()
233
MutableSet<String> set = this.newWith("1", "2", "3", "4");
234
LazyIterable<Pair<String, String>> cartesianProduct = set.cartesianProduct(UnifiedSet.newSetWith("One", "Two"));
235
Verify.assertIterableSize(set.size() * 2, cartesianProduct);
239
.select(Predicates.attributeEqual((Function<Pair<?, String>, String>) Pair::getTwo, "One"))
240
.collect((Function<Pair<String, ?>, String>) Pair::getOne).toSet());
245
public void asUnmodifiable()
247
Verify.assertInstanceOf(UnmodifiableMutableSet.class, this.newWith().asUnmodifiable());
255
Verify.assertContainsAll(this.newWith(1, 2, 3, 4, 5).select(Predicates.lessThan(3)), 1, 2);
256
Verify.assertContainsAll(
257
this.newWith(-1, 2, 3, 4, 5).select(Predicates.lessThan(3),
258
FastList.<Integer>newList()), -1, 2);
266
Verify.assertContainsAll(this.newWith(1, 2, 3, 4).reject(Predicates.lessThan(3)), 3, 4);
267
Verify.assertContainsAll(
268
this.newWith(1, 2, 3, 4).reject(Predicates.lessThan(3),
269
FastList.<Integer>newList()), 3, 4);
274
public void getFirst()
278
Assert.assertNotNull(this.newWith(1, 2, 3).getFirst());
279
Assert.assertNull(this.newWith().getFirst());
284
public void getLast()
286
Assert.assertNotNull(this.newWith(1, 2, 3).getLast());
287
Assert.assertNull(this.newWith().getLast());
291
public void unifiedSetKeySetToArrayDest()
293
MutableSet<Integer> set = this.newWith(1, 2, 3, 4);
294
// deliberately to small to force the method to allocate one of the correct size
295
Integer[] dest = new Integer[2];
296
Integer[] result = set.toArray(dest);
297
Verify.assertSize(4, result);
299
Assert.assertArrayEquals(new Integer[]{1, 2, 3, 4}, result);
303
public void unifiedSetToString()
305
MutableSet<Integer> set = this.newWith(1, 2);
306
String s = set.toString();
307
Assert.assertTrue("[1, 2]".equals(s) || "[2, 1]".equals(s));
311
public void testClone()
313
MutableSet<String> set = this.newWith();
314
MutableSet<String> clone = set.clone();
315
Assert.assertNotSame(clone, set);
316
Verify.assertEqualsAndHashCode(clone, set);
321
public void isEmpty()
325
MutableSet<String> set = this.newWith();
326
this.assertIsEmpty(true, set);
329
this.assertIsEmpty(false, set);
332
this.assertIsEmpty(true, set);
336
this.assertIsEmpty(false, set);
338
this.assertIsEmpty(false, set);
340
this.assertIsEmpty(true, set);
343
private void assertIsEmpty(boolean isEmpty, MutableSet<?> set)
345
Assert.assertEquals(isEmpty, set.isEmpty());
346
Assert.assertEquals(!isEmpty, set.notEmpty());
352
MutableSet<IntegerWithCast> set = this.newWith();
353
MutableList<IntegerWithCast> collisions = COLLISIONS.collect(IntegerWithCast::new);
354
set.addAll(collisions);
355
set.removeAll(collisions);
356
for (Integer integer : COLLISIONS)
358
Assert.assertTrue(set.add(new IntegerWithCast(integer)));
359
Assert.assertFalse(set.add(new IntegerWithCast(integer)));
361
Assert.assertEquals(collisions.toSet(), set);
370
MutableSet<IntegerWithCast> set = this.newWith();
371
MutableList<IntegerWithCast> collisions = COLLISIONS.collect(IntegerWithCast::new);
372
set.addAll(collisions);
373
collisions.reverseForEach(each -> {
374
Assert.assertFalse(set.remove(null));
375
Assert.assertTrue(set.remove(each));
376
Assert.assertFalse(set.remove(each));
377
Assert.assertFalse(set.remove(null));
378
Assert.assertFalse(set.remove(new IntegerWithCast(COLLISION_10)));
381
Assert.assertEquals(UnifiedSet.<IntegerWithCast>newSet(), set);
383
collisions.forEach(Procedures.cast(each -> {
384
MutableSet<IntegerWithCast> set2 = this.newWith();
385
set2.addAll(collisions);
387
Assert.assertFalse(set2.remove(null));
388
Assert.assertTrue(set2.remove(each));
389
Assert.assertFalse(set2.remove(each));
390
Assert.assertFalse(set2.remove(null));
391
Assert.assertFalse(set2.remove(new IntegerWithCast(COLLISION_10)));
394
// remove the second-to-last item in a fully populated single chain to cause the last item to move
395
MutableSet<Integer> set3 = this.newWith(COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4);
396
Assert.assertTrue(set3.remove(COLLISION_3));
397
Assert.assertEquals(UnifiedSet.newSetWith(COLLISION_1, COLLISION_2, COLLISION_4), set3);
399
Assert.assertTrue(set3.remove(COLLISION_2));
400
Assert.assertEquals(UnifiedSet.newSetWith(COLLISION_1, COLLISION_4), set3);
402
// search a chain for a non-existent element
403
MutableSet<Integer> chain = this.newWith(COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4);
404
Assert.assertFalse(chain.remove(COLLISION_5));
406
// search a deep chain for a non-existent element
407
MutableSet<Integer> deepChain = this.newWith(COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4, COLLISION_5, COLLISION_6, COLLISION_7);
408
Assert.assertFalse(deepChain.remove(COLLISION_8));
410
// search for a non-existent element
411
MutableSet<Integer> empty = this.newWith();
412
Assert.assertFalse(empty.remove(COLLISION_1));
417
public void retainAll()
421
MutableList<Integer> collisions = MORE_COLLISIONS.clone();
422
collisions.add(COLLISION_10);
424
int size = MORE_COLLISIONS.size();
425
for (int i = 0; i < size; i++)
427
MutableList<Integer> list = MORE_COLLISIONS.subList(0, i);
428
MutableSet<Integer> set = this.<Integer>newWith().withAll(list);
429
Assert.assertFalse(set.retainAll(collisions));
430
Assert.assertEquals(list.toSet(), set);
433
for (Integer item : MORE_COLLISIONS)
435
MutableSet<Integer> integers = this.<Integer>newWith().withAll(MORE_COLLISIONS);
436
@SuppressWarnings("BoxingBoxedValue")
437
Integer keyCopy = new Integer(item);
438
Assert.assertTrue(integers.retainAll(mList(keyCopy)));
439
Assert.assertEquals(iSet(keyCopy), integers);
440
Assert.assertNotSame(keyCopy, Iterate.getOnly(integers));
443
// retain all on a bucket with a single element
444
MutableSet<Integer> singleCollisionBucket = this.newWith(COLLISION_1, COLLISION_2);
445
singleCollisionBucket.remove(COLLISION_2);
446
Assert.assertTrue(singleCollisionBucket.retainAll(FastList.newListWith(COLLISION_2)));
451
public void equalsAndHashCode()
453
super.equalsAndHashCode();
455
UnifiedSet<Integer> expected = UnifiedSet.newSetWith(COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4);
456
Assert.assertNotEquals(expected, this.newWith(COLLISION_2, COLLISION_3, COLLISION_4, COLLISION_5));
457
Assert.assertNotEquals(expected, this.newWith(COLLISION_1, COLLISION_3, COLLISION_4, COLLISION_5));
458
Assert.assertNotEquals(expected, this.newWith(COLLISION_1, COLLISION_2, COLLISION_4, COLLISION_5));
459
Assert.assertNotEquals(expected, this.newWith(COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_5));
461
Assert.assertEquals(expected, this.newWith(COLLISION_1, COLLISION_2, COLLISION_3, COLLISION_4));
466
public void forEach()
470
int size = MORE_COLLISIONS.size();
471
for (int i = 1; i < size; i++)
473
MutableSet<Integer> set = this.newWith();
474
set.addAll(MORE_COLLISIONS.subList(0, i));
475
MutableSet<Integer> result = UnifiedSet.newSet();
476
set.forEach(CollectionAddProcedure.on(result));
477
Assert.assertEquals(set, result);
480
// test iterating on a bucket with only one element
481
MutableSet<Integer> set = this.newWith(COLLISION_1, COLLISION_2);
482
set.remove(COLLISION_2);
483
Counter counter = new Counter();
484
set.forEach(Procedures.cast(each -> counter.increment()));
485
Assert.assertEquals(1, counter.getCount());
490
public void forEachWith()
494
Object sentinel = new Object();
495
int size = MORE_COLLISIONS.size();
496
for (int i = 1; i < size; i++)
498
MutableSet<Integer> set = this.newWith();
499
set.addAll(MORE_COLLISIONS.subList(0, i));
500
MutableSet<Integer> result = UnifiedSet.newSet();
502
set.forEachWith((argument1, argument2) -> {
503
Assert.assertSame(sentinel, argument2);
504
result.add(argument1);
506
Assert.assertEquals(set, result);
509
// test iterating on a bucket with only one element
510
MutableSet<Integer> set = this.newWith(COLLISION_1, COLLISION_2);
511
set.remove(COLLISION_2);
512
Counter counter = new Counter();
513
set.forEachWith((argument1, argument2) -> argument2.increment(), counter);
514
Assert.assertEquals(1, counter.getCount());
519
public void forEachWithIndex()
521
super.forEachWithIndex();
523
int size = MORE_COLLISIONS.size();
524
for (int i = 1; i < size; i++)
526
MutableSet<Integer> set = this.newWith();
527
set.addAll(MORE_COLLISIONS.subList(0, i));
528
MutableSet<Integer> result = UnifiedSet.newSet();
529
MutableList<Integer> indexes = Lists.mutable.of();
530
set.forEachWithIndex((each, index) -> {
534
Assert.assertEquals(set, result);
535
Assert.assertEquals(Interval.zeroTo(i - 1), indexes);
538
// test iterating on a bucket with only one element
539
UnifiedSet<Integer> set = UnifiedSet.newSetWith(COLLISION_1, COLLISION_2);
540
set.remove(COLLISION_2);
541
Counter counter = new Counter();
542
set.forEachWithIndex((each, index) -> counter.increment());
543
Assert.assertEquals(1, counter.getCount());
548
public void anySatisfy()
552
int size = MORE_COLLISIONS.size();
553
for (int i = 1; i < size; i++)
555
MutableSet<Integer> set = this.newWith();
556
set.addAll(MORE_COLLISIONS.subList(0, i));
557
Assert.assertTrue(set.anySatisfy(MORE_COLLISIONS.subList(0, i).getLast()::equals));
558
Assert.assertFalse(set.anySatisfy(Predicates.greaterThan(MORE_COLLISIONS.subList(0, i).getLast())));
561
// test anySatisfy on a bucket with only one element
562
MutableSet<Integer> set = this.newWith(COLLISION_1, COLLISION_2);
563
set.remove(COLLISION_2);
564
Assert.assertTrue(set.anySatisfy(COLLISION_1::equals));
565
Assert.assertFalse(set.anySatisfy(COLLISION_2::equals));
567
// Rehashing Case A: a bucket with only one entry and a low capacity forcing a rehash, where the triggering element goes in the bucket
568
// set up a chained bucket
569
MutableSet<Integer> caseA = this.newWith(COLLISION_1, COLLISION_2);
570
// clear the bucket to one element
571
caseA.remove(COLLISION_2);
572
// increase the occupied count to the threshold
573
caseA.add(Integer.valueOf(1));
574
caseA.add(Integer.valueOf(2));
576
// add the colliding value back and force the rehash
577
caseA.add(COLLISION_2);
578
Assert.assertTrue(caseA.anySatisfy(COLLISION_2::equals));
583
public void allSatisfy()
587
int size = MORE_COLLISIONS.size();
588
for (int i = 1; i < size; i++)
590
MutableSet<Integer> set = this.newWith();
591
set.addAll(MORE_COLLISIONS.subList(0, i));
592
Assert.assertTrue(set.allSatisfy(Predicates.greaterThanOrEqualTo(MORE_COLLISIONS.subList(0, i).getFirst())));
593
Assert.assertFalse(set.allSatisfy(Predicates.lessThan(MORE_COLLISIONS.subList(0, i).get(i - 1))));
596
// test allSatisfy on a bucket with only one element
597
MutableSet<Integer> set = this.newWith(COLLISION_1, COLLISION_2);
598
set.remove(COLLISION_2);
599
Assert.assertTrue(set.allSatisfy(COLLISION_1::equals));
600
Assert.assertFalse(set.allSatisfy(COLLISION_2::equals));
602
// Rehashing Case A: a bucket with only one entry and a low capacity forcing a rehash, where the triggering element goes in the bucket
603
// set up a chained bucket
604
MutableSet<Integer> caseA = this.newWith(COLLISION_1, COLLISION_2);
605
// clear the bucket to one element
606
caseA.remove(COLLISION_2);
607
// increase the occupied count to the threshold
608
caseA.add(Integer.valueOf(1));
609
caseA.add(Integer.valueOf(2));
611
// add the colliding value back and force the rehash
612
caseA.add(COLLISION_2);
613
Assert.assertTrue(caseA.allSatisfy(Predicates.lessThanOrEqualTo(COLLISION_2)));
622
int size = MORE_COLLISIONS.size();
623
for (int i = 1; i < size; i++)
625
MutableSet<Integer> set = this.newWith();
626
set.addAll(MORE_COLLISIONS.subList(0, i));
627
Verify.assertItemAtIndex(set.detect(MORE_COLLISIONS.get(i - 1)::equals), i - 1, MORE_COLLISIONS);
630
// test detect on a bucket with only one element
631
MutableSet<Integer> set = this.newWith(COLLISION_1, COLLISION_2);
632
set.remove(COLLISION_2);
633
Assert.assertEquals(COLLISION_1, set.detect(COLLISION_1::equals));
634
Assert.assertNull(set.detect(COLLISION_2::equals));
636
for (int i = 0; i < COLLISIONS.size(); i++)
638
MutableSet<Integer> rehashingSet = this.newWith();
639
rehashingSet.addAll(COLLISIONS.subList(0, i));
640
Integer last = COLLISIONS.subList(0, i).getLast();
641
rehashingSet.remove(last);
643
int rehashingSetSize = rehashingSet.size();
644
for (int j = 0; j < rehashingSetSize; j++)
646
rehashingSet.add(Integer.valueOf(j + 1));
649
rehashingSet.add(last);
650
Assert.assertEquals(last, rehashingSet.detect(Predicates.equal(last)));
651
Assert.assertNull(rehashingSet.detect(Integer.valueOf(5)::equals));
655
@Test(expected = NoSuchElementException.class)
656
public void iterator_increment_past_end()
658
MutableSet<Integer> set = this.newWith();
659
Iterator<Integer> iterator = set.iterator();
664
@Test(expected = IllegalStateException.class)
665
public void iterator_remove_without_next()
667
Iterator<Integer> iterator = this.<Integer>newWith().iterator();
673
public void toArray()
677
MutableSet<Integer> integers = this.newWith(1);
678
Integer[] target = new Integer[3];
682
integers.toArray(target);
683
Assert.assertArrayEquals(new Integer[]{1, null, 2}, target);