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