View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections4.list;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertSame;
22  import static org.junit.jupiter.api.Assertions.assertThrows;
23  import static org.junit.jupiter.api.Assertions.assertTrue;
24  
25  import java.util.ArrayList;
26  import java.util.Arrays;
27  import java.util.Collection;
28  import java.util.HashSet;
29  import java.util.LinkedList;
30  import java.util.List;
31  import java.util.ListIterator;
32  import java.util.Set;
33  import java.util.TreeSet;
34  
35  import org.apache.commons.collections4.set.UnmodifiableSet;
36  import org.apache.commons.lang3.StringUtils;
37  import org.junit.jupiter.api.Test;
38  
39  /**
40   * JUnit tests.
41   */
42  public class SetUniqueListTest<E> extends AbstractListTest<E> {
43  
44      final class SetUniqueList307 extends SetUniqueList<E> {
45          /**
46           * Generated serial version ID.
47           */
48          private static final long serialVersionUID = 1415013031022962158L;
49  
50          SetUniqueList307(final List<E> list, final Set<E> set) {
51              super(list, set);
52          }
53      }
54  
55      boolean extraVerify = true;
56  
57      public SetUniqueListTest() {
58          super(SetUniqueListTest.class.getSimpleName());
59      }
60  
61      @Override
62      public String getCompatibilityVersion() {
63          return "4";
64      }
65  
66      @Override
67      @SuppressWarnings("unchecked")
68      public E[] getFullNonNullElements() {
69          // override to avoid duplicate "One"
70          return (E[]) new Object[] {
71              StringUtils.EMPTY,
72              "One",
73              Integer.valueOf(2),
74              "Three",
75              Integer.valueOf(4),
76              Double.valueOf(5),
77              Float.valueOf(6),
78              "Seven",
79              "Eight",
80              "Nine",
81              Integer.valueOf(10),
82              Short.valueOf((short) 11),
83              Long.valueOf(12),
84              "Thirteen",
85              "14",
86              "15",
87              Byte.valueOf((byte) 16)
88          };
89      }
90  
91      @Override
92      public List<E> makeObject() {
93          return new SetUniqueList<>(new ArrayList<>(), new HashSet<>());
94      }
95  
96      @Test
97      @SuppressWarnings("unchecked")
98      public void testAdd() {
99          final SetUniqueList<E> lset = new SetUniqueList<>(new ArrayList<>(), new HashSet<>());
100 
101         // Duplicate element
102         final E obj = (E) Integer.valueOf(1);
103         lset.add(obj);
104         lset.add(obj);
105         assertEquals(1, lset.size(), "Duplicate element was added.");
106 
107         // Unique element
108         lset.add((E) Integer.valueOf(2));
109         assertEquals(2, lset.size(), "Unique element was not added.");
110     }
111 
112     @Test
113     @SuppressWarnings("unchecked")
114     public void testAddAll() {
115         final SetUniqueList<E> lset = new SetUniqueList<>(new ArrayList<>(), new HashSet<>());
116 
117         lset.addAll(
118             Arrays.asList((E[]) new Integer[] { Integer.valueOf(1), Integer.valueOf(1)}));
119 
120         assertEquals(1, lset.size(), "Duplicate element was added.");
121     }
122 
123     @Test
124     @Override
125     public void testCollectionAddAll() {
126         // override for set behavior
127         resetEmpty();
128         E[] elements = getFullElements();
129         boolean r = getCollection().addAll(Arrays.asList(elements));
130         getConfirmed().addAll(Arrays.asList(elements));
131         verify();
132         assertTrue(r, "Empty collection should change after addAll");
133         for (final E element : elements) {
134             assertTrue(getCollection().contains(element),
135                     "Collection should contain added element");
136         }
137 
138         resetFull();
139         final int size = getCollection().size();
140         elements = getOtherElements();
141         r = getCollection().addAll(Arrays.asList(elements));
142         getConfirmed().addAll(Arrays.asList(elements));
143         verify();
144         assertTrue(r, "Full collection should change after addAll");
145         for (int i = 0; i < elements.length; i++) {
146             assertTrue(getCollection().contains(elements[i]),
147                     "Full collection should contain added element " + i);
148         }
149         assertEquals(size + elements.length, getCollection().size(),
150                 "Size should increase after addAll");
151     }
152 
153     @Test
154     @Override
155     public void testCollectionIteratorRemove() {
156         try {
157             extraVerify = false;
158             super.testCollectionIteratorRemove();
159         } finally {
160             extraVerify = true;
161         }
162     }
163     @Test
164     public void testCollections304() {
165         final List<String> list = new LinkedList<>();
166         final SetUniqueList<String> decoratedList = SetUniqueList.setUniqueList(list);
167         final String s1 = "Apple";
168         final String s2 = "Lemon";
169         final String s3 = "Orange";
170         final String s4 = "Strawberry";
171 
172         decoratedList.add(s1);
173         decoratedList.add(s2);
174         decoratedList.add(s3);
175         assertEquals(3, decoratedList.size());
176 
177         decoratedList.set(1, s4);
178         assertEquals(3, decoratedList.size());
179 
180         decoratedList.add(1, s4);
181         assertEquals(3, decoratedList.size());
182 
183         decoratedList.add(1, s2);
184         assertEquals(4, decoratedList.size());
185     }
186 
187     @Test
188     @SuppressWarnings("unchecked")
189     public void testCollections307() {
190         List<E> list = new ArrayList<>();
191         List<E> uniqueList = SetUniqueList.setUniqueList(list);
192 
193         final String hello = "Hello";
194         final String world = "World";
195         uniqueList.add((E) hello);
196         uniqueList.add((E) world);
197 
198         List<E> subList = list.subList(0, 0);
199         List<E> subUniqueList = uniqueList.subList(0, 0);
200 
201         assertFalse(subList.contains(world)); // passes
202         assertFalse(subUniqueList.contains(world)); // fails
203 
204         List<E> worldList = new ArrayList<>();
205         worldList.add((E) world);
206         assertFalse(subList.contains("World")); // passes
207         assertFalse(subUniqueList.contains("World")); // fails
208 
209         // repeat the test with a different class than HashSet;
210         // which means subclassing SetUniqueList below
211         list = new ArrayList<>();
212         uniqueList = new SetUniqueList307(list, new TreeSet<>());
213 
214         uniqueList.add((E) hello);
215         uniqueList.add((E) world);
216 
217         subList = list.subList(0, 0);
218         subUniqueList = uniqueList.subList(0, 0);
219 
220         assertFalse(subList.contains(world)); // passes
221         assertFalse(subUniqueList.contains(world)); // fails
222 
223         worldList = new ArrayList<>();
224         worldList.add((E) world);
225         assertFalse(subList.contains("World")); // passes
226         assertFalse(subUniqueList.contains("World")); // fails
227     }
228 
229     @Test
230     public void testCollections701() {
231         final SetUniqueList<Object> uniqueList = new SetUniqueList<>(new ArrayList<>(), new HashSet<>());
232         final Integer obj1 = Integer.valueOf(1);
233         final Integer obj2 = Integer.valueOf(2);
234         uniqueList.add(obj1);
235         uniqueList.add(obj2);
236         assertEquals(2, uniqueList.size());
237         uniqueList.add(uniqueList);
238         assertEquals(3, uniqueList.size());
239         final List<Object> list = new LinkedList<>();
240         final SetUniqueList<Object> decoratedList = SetUniqueList.setUniqueList(list);
241         final String s1 = "Apple";
242         final String s2 = "Lemon";
243         final String s3 = "Orange";
244         final String s4 = "Strawberry";
245         decoratedList.add(s1);
246         decoratedList.add(s2);
247         decoratedList.add(s3);
248         assertEquals(3, decoratedList.size());
249         decoratedList.set(1, s4);
250         assertEquals(3, decoratedList.size());
251         decoratedList.add(decoratedList);
252         assertEquals(4, decoratedList.size());
253     }
254 
255     @Test
256     @SuppressWarnings("unchecked")
257     public void testCreateSetBasedOnList() {
258         final List<String> list = new ArrayList<>();
259         list.add("One");
260         list.add("Two");
261         @SuppressWarnings("rawtypes") final SetUniqueList setUniqueList = (SetUniqueList) makeObject();
262 
263         // Standard case with HashSet
264         final Set<String> setBasedOnList = setUniqueList.createSetBasedOnList(new HashSet<>(), list);
265         assertEquals(list.size(), setBasedOnList.size());
266         list.forEach(item -> assertTrue(setBasedOnList.contains(item)));
267 
268         // Use different Set than HashSet
269         final Set<String> setBasedOnList1 = setUniqueList.createSetBasedOnList(new TreeSet<>(), list);
270         assertEquals(list.size(), setBasedOnList1.size());
271         list.forEach(item -> assertTrue(setBasedOnList1.contains(item)));
272 
273         // throws internally NoSuchMethodException --> results in HashSet
274         final Set<String> setBasedOnList2 = setUniqueList.createSetBasedOnList(UnmodifiableSet.unmodifiableSet(new HashSet<>()), list);
275         assertEquals(list.size(), setBasedOnList2.size());
276         list.forEach(item -> assertTrue(setBasedOnList2.contains(item)));
277 
278         // provide null values as Parameter
279         assertThrows(NullPointerException.class, () -> setUniqueList.createSetBasedOnList(null, list));
280         assertThrows(NullPointerException.class, () -> setUniqueList.createSetBasedOnList(new HashSet<>(), null));
281     }
282 
283     @Test
284     public void testFactory() {
285         final Integer[] array = { Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(1) };
286         final ArrayList<Integer> list = new ArrayList<>(Arrays.asList(array));
287         final SetUniqueList<Integer> lset = SetUniqueList.setUniqueList(list);
288 
289         assertEquals(2, lset.size(), "Duplicate element was added.");
290         assertEquals(Integer.valueOf(1), lset.get(0));
291         assertEquals(Integer.valueOf(2), lset.get(1));
292         assertEquals(Integer.valueOf(1), list.get(0));
293         assertEquals(Integer.valueOf(2), list.get(1));
294     }
295 
296     @Test
297     public void testIntCollectionAddAll() {
298         // make a SetUniqueList with one element
299         final List<Integer> list = new SetUniqueList<>(new ArrayList<>(), new HashSet<>());
300         final Integer existingElement = Integer.valueOf(1);
301         list.add(existingElement);
302 
303         // add two new unique elements at index 0
304         final Integer firstNewElement = Integer.valueOf(2);
305         final Integer secondNewElement = Integer.valueOf(3);
306         Collection<Integer> collection = Arrays.asList(firstNewElement, secondNewElement);
307         list.addAll(0, collection);
308         assertEquals(3, list.size(), "Unique elements should be added.");
309         assertEquals(firstNewElement, list.get(0), "First new element should be at index 0");
310         assertEquals(secondNewElement, list.get(1), "Second new element should be at index 1");
311         assertEquals(existingElement, list.get(2), "Existing element should shift to index 2");
312 
313         // add a duplicate element and a unique element at index 0
314         final Integer thirdNewElement = Integer.valueOf(4);
315         collection = Arrays.asList(existingElement, thirdNewElement);
316         list.addAll(0, collection);
317         assertEquals(4, list.size(),
318                 "Duplicate element should not be added, unique element should be added.");
319         assertEquals(thirdNewElement, list.get(0), "Third new element should be at index 0");
320     }
321 
322     @Test
323     @SuppressWarnings("unchecked")
324     public void testListIterator() {
325         final SetUniqueList<E> lset = new SetUniqueList<>(new ArrayList<>(), new HashSet<>());
326 
327         final E obj1 = (E) Integer.valueOf(1);
328         final E obj2 = (E) Integer.valueOf(2);
329         lset.add(obj1);
330         lset.add(obj2);
331 
332         // Attempts to add a duplicate object
333         for (final ListIterator<E> it = lset.listIterator(); it.hasNext();) {
334             it.next();
335 
336             if (!it.hasNext()) {
337                 it.add(obj1);
338                 break;
339             }
340         }
341 
342         assertEquals(2, lset.size(), "Duplicate element was added");
343     }
344 
345     @Test
346     @Override
347     public void testListIteratorAdd() {
348         // override to cope with Set behavior
349         resetEmpty();
350         final List<E> list1 = getCollection();
351         final List<E> list2 = getConfirmed();
352 
353         final E[] elements = getOtherElements();  // changed here
354         ListIterator<E> iter1 = list1.listIterator();
355         ListIterator<E> iter2 = list2.listIterator();
356 
357         for (final E element : elements) {
358             iter1.add(element);
359             iter2.add(element);
360             super.verify();  // changed here
361         }
362 
363         resetFull();
364         iter1 = getCollection().listIterator();
365         iter2 = getConfirmed().listIterator();
366         for (final E element : elements) {
367             iter1.next();
368             iter2.next();
369             iter1.add(element);
370             iter2.add(element);
371             super.verify();  // changed here
372         }
373     }
374 
375     @Test
376     @Override
377     public void testListIteratorSet() {
378         // override to block
379         resetFull();
380         final ListIterator<E> it = getCollection().listIterator();
381         it.next();
382 
383         assertThrows(UnsupportedOperationException.class, () -> it.set(null));
384     }
385 
386     @Test
387     @Override
388     @SuppressWarnings("unchecked")
389     public void testListSetByIndex() {
390         // override for set behavior
391         resetFull();
392         final int size = getCollection().size();
393         getCollection().set(0, (E) Long.valueOf(1000));
394         assertEquals(size, getCollection().size());
395 
396         getCollection().set(2, (E) Long.valueOf(1000));
397         assertEquals(size - 1, getCollection().size());
398         assertEquals(Long.valueOf(1000), getCollection().get(1));  // set into 2, but shifted down to 1
399     }
400 
401     @Test
402     @SuppressWarnings("unchecked")
403     public void testRetainAll() {
404         final List<E> list = new ArrayList<>(10);
405         final SetUniqueList<E> uniqueList = SetUniqueList.setUniqueList(list);
406         for (int i = 0; i < 10; ++i) {
407             uniqueList.add((E) Integer.valueOf(i));
408         }
409 
410         final Collection<E> retained = new ArrayList<>(5);
411         for (int i = 0; i < 5; ++i) {
412             retained.add((E) Integer.valueOf(i * 2));
413         }
414 
415         assertTrue(uniqueList.retainAll(retained));
416         assertEquals(5, uniqueList.size());
417         assertTrue(uniqueList.contains(Integer.valueOf(0)));
418         assertTrue(uniqueList.contains(Integer.valueOf(2)));
419         assertTrue(uniqueList.contains(Integer.valueOf(4)));
420         assertTrue(uniqueList.contains(Integer.valueOf(6)));
421         assertTrue(uniqueList.contains(Integer.valueOf(8)));
422     }
423 
424     @Test
425     @SuppressWarnings("unchecked")
426     public void testRetainAllWithInitialList() {
427         // initialized with empty list
428         final List<E> list = new ArrayList<>(10);
429         for (int i = 0; i < 5; ++i) {
430             list.add((E) Integer.valueOf(i));
431         }
432         final SetUniqueList<E> uniqueList = SetUniqueList.setUniqueList(list);
433         for (int i = 5; i < 10; ++i) {
434             uniqueList.add((E) Integer.valueOf(i));
435         }
436 
437         final Collection<E> retained = new ArrayList<>(5);
438         for (int i = 0; i < 5; ++i) {
439             retained.add((E) Integer.valueOf(i * 2));
440         }
441 
442         assertTrue(uniqueList.retainAll(retained));
443         assertEquals(5, uniqueList.size());
444         assertTrue(uniqueList.contains(Integer.valueOf(0)));
445         assertTrue(uniqueList.contains(Integer.valueOf(2)));
446         assertTrue(uniqueList.contains(Integer.valueOf(4)));
447         assertTrue(uniqueList.contains(Integer.valueOf(6)));
448         assertTrue(uniqueList.contains(Integer.valueOf(8)));
449     }
450 
451     @Test
452     @SuppressWarnings("unchecked")
453     public void testSet() {
454         final SetUniqueList<E> lset = new SetUniqueList<>(new ArrayList<>(), new HashSet<>());
455 
456         // Duplicate element
457         final E obj1 = (E) Integer.valueOf(1);
458         final E obj2 = (E) Integer.valueOf(2);
459         final E obj3 = (E) Integer.valueOf(3);
460 
461         lset.add(obj1);
462         lset.add(obj2);
463         lset.set(0, obj1);
464         assertEquals(2, lset.size());
465         assertSame(obj1, lset.get(0));
466         assertSame(obj2, lset.get(1));
467 
468         lset.clear();
469         lset.add(obj1);
470         lset.add(obj2);
471         lset.set(0, obj2);
472         assertEquals(1, lset.size());
473         assertSame(obj2, lset.get(0));
474 
475         lset.clear();
476         lset.add(obj1);
477         lset.add(obj2);
478         lset.set(0, obj3);
479         assertEquals(2, lset.size());
480         assertSame(obj3, lset.get(0));
481         assertSame(obj2, lset.get(1));
482 
483         lset.clear();
484         lset.add(obj1);
485         lset.add(obj2);
486         lset.set(1, obj1);
487         assertEquals(1, lset.size());
488         assertSame(obj1, lset.get(0));
489     }
490 
491     @Test
492     public void testSetCollections444() {
493         final SetUniqueList<Integer> lset = new SetUniqueList<>(new ArrayList<>(), new HashSet<>());
494 
495         // Duplicate element
496         final Integer obj1 = Integer.valueOf(1);
497         final Integer obj2 = Integer.valueOf(2);
498 
499         lset.add(obj1);
500         lset.add(obj2);
501         lset.set(0, obj1);
502         assertEquals(2, lset.size());
503         assertSame(obj1, lset.get(0));
504         assertSame(obj2, lset.get(1));
505 
506         assertTrue(lset.contains(obj1));
507         assertTrue(lset.contains(obj2));
508     }
509     @Test
510     @SuppressWarnings("unchecked")
511     public void testSetDownwardsInList() {
512         /*
513          * Checks the following semantics
514          * [a,b]
515          * set(0,b): [b]->a
516          * So UniqList contains [b] and a is returned
517          */
518         final ArrayList<E> l = new ArrayList<>();
519         final HashSet<E> s = new HashSet<>();
520         final SetUniqueList<E> ul = new SetUniqueList<>(l, s);
521 
522         final E a = (E) new Object();
523         final E b = (E) new Object();
524         ul.add(a);
525         ul.add(b);
526         assertEquals(a, l.get(0));
527         assertEquals(b, l.get(1));
528         assertTrue(s.contains(a));
529         assertTrue(s.contains(b));
530 
531         assertEquals(a, ul.set(0, b));
532         assertEquals(1, s.size());
533         assertEquals(1, l.size());
534         assertEquals(b, l.get(0));
535         assertTrue(s.contains(b));
536         assertFalse(s.contains(a));
537     }
538 
539     @Test
540     @SuppressWarnings("unchecked")
541     public void testSetInBiggerList() {
542         /*
543          * Checks the following semantics
544          * [a,b,c]
545          * set(0,b): [b,c]->a
546          * So UniqList contains [b,c] and a is returned
547          */
548         final ArrayList<E> l = new ArrayList<>();
549         final HashSet<E> s = new HashSet<>();
550         final SetUniqueList<E> ul = new SetUniqueList<>(l, s);
551 
552         final E a = (E) new Object();
553         final E b = (E) new Object();
554         final E c = (E) new Object();
555 
556         ul.add(a);
557         ul.add(b);
558         ul.add(c);
559         assertEquals(a, l.get(0));
560         assertEquals(b, l.get(1));
561         assertEquals(c, l.get(2));
562         assertTrue(s.contains(a));
563         assertTrue(s.contains(b));
564         assertTrue(s.contains(c));
565 
566         assertEquals(a, ul.set(0, b));
567         assertEquals(2, s.size());
568         assertEquals(2, l.size());
569         assertEquals(b, l.get(0));
570         assertEquals(c, l.get(1));
571         assertFalse(s.contains(a));
572         assertTrue(s.contains(b));
573         assertTrue(s.contains(c));
574     }
575 
576     @Test
577     @SuppressWarnings("unchecked")
578     public void testSetUpwardsInList() {
579         /*
580          * Checks the following semantics
581          * [a,b,c]
582          * set(1,a): [a,c]->b
583          * So UniqList contains [a,c] and b is returned
584          */
585         final ArrayList<E> l = new ArrayList<>();
586         final HashSet<E> s = new HashSet<>();
587         final SetUniqueList<E> ul = new SetUniqueList<>(l, s);
588 
589         final E a = (E) "A";
590         final E b = (E) "B";
591         final E c = (E) "C";
592 
593         ul.add(a);
594         ul.add(b);
595         ul.add(c);
596         assertEquals(a, l.get(0));
597         assertEquals(b, l.get(1));
598         assertEquals(c, l.get(2));
599         assertTrue(s.contains(a));
600         assertTrue(s.contains(b));
601         assertTrue(s.contains(c));
602 
603         assertEquals(b, ul.set(1, a));
604         assertEquals(2, s.size());
605         assertEquals(2, l.size());
606         assertEquals(a, l.get(0));
607         assertEquals(c, l.get(1));
608         assertTrue(s.contains(a));
609         assertFalse(s.contains(b));
610         assertTrue(s.contains(c));
611     }
612 
613     @Test
614     public void testSubListIsUnmodifiable() {
615         resetFull();
616         final List<E> subList = getCollection().subList(1, 3);
617         assertEquals(2, subList.size());
618         assertThrows(UnsupportedOperationException.class, () -> subList.remove(0));
619     }
620 
621     @Test
622     @SuppressWarnings("unchecked")
623     public void testUniqueListDoubleInsert() {
624         final List<E> l = SetUniqueList.setUniqueList(new LinkedList<>());
625         l.add((E) new Object());
626         l.add((E) new Object());
627 
628         // duplicate is removed
629         l.set(0, l.get(1));
630         assertEquals(1, l.size());
631 
632         // duplicate should be removed again
633         l.add(1, l.get(0));
634         assertEquals(1, l.size());
635     }
636 
637     @Test
638     @SuppressWarnings("unchecked")
639     public void testUniqueListReInsert() {
640         final List<E> l = SetUniqueList.setUniqueList(new LinkedList<>());
641         l.add((E) new Object());
642         l.add((E) new Object());
643 
644         final E a = l.get(0);
645 
646         // duplicate is removed
647         l.set(0, l.get(1));
648         assertEquals(1, l.size());
649 
650         // old object is added back in
651         l.add(1, a);
652         assertEquals(2, l.size());
653     }
654 
655     @Override
656     @SuppressWarnings("unchecked")
657     public void verify() {
658         super.verify();
659 
660         if (extraVerify) {
661             final int size = getCollection().size();
662             getCollection().add((E) Long.valueOf(1000));
663             assertEquals(size + 1, getCollection().size());
664 
665             getCollection().add((E) Long.valueOf(1000));
666             assertEquals(size + 1, getCollection().size());
667             assertEquals(Long.valueOf(1000), getCollection().get(size));
668 
669             getCollection().remove(size);
670         }
671     }
672 
673 }