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;
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.assertInstanceOf;
22  import static org.junit.jupiter.api.Assertions.assertNotEquals;
23  import static org.junit.jupiter.api.Assertions.assertNotNull;
24  import static org.junit.jupiter.api.Assertions.assertSame;
25  import static org.junit.jupiter.api.Assertions.assertThrows;
26  import static org.junit.jupiter.api.Assertions.assertTrue;
27  
28  import java.util.ArrayList;
29  import java.util.Arrays;
30  import java.util.Collection;
31  import java.util.Collections;
32  import java.util.HashSet;
33  import java.util.List;
34  
35  import org.apache.commons.collections4.functors.EqualPredicate;
36  import org.apache.commons.collections4.list.PredicatedList;
37  import org.apache.commons.lang3.StringUtils;
38  import org.junit.jupiter.api.BeforeEach;
39  import org.junit.jupiter.api.Test;
40  
41  /**
42   * Tests for ListUtils.
43   */
44  public class ListUtilsTest {
45  
46      private static final String a = "a";
47      private static final String b = "b";
48      private static final String c = "c";
49      private static final String d = "d";
50      private static final String e = "e";
51      private static final String x = "x";
52  
53      private static final Predicate<Number> EQUALS_TWO = input -> input.intValue() == 2;
54      private String[] fullArray;
55  
56      private List<String> fullList;
57  
58      @BeforeEach
59      public void setUp() {
60          fullArray = new String[]{a, b, c, d, e};
61          fullList = new ArrayList<>(Arrays.asList(fullArray));
62      }
63  
64      @Test
65      public void testDefaultIfNull() {
66          assertTrue(ListUtils.defaultIfNull(null, Collections.emptyList()).isEmpty());
67  
68          final List<Long> list = new ArrayList<>();
69          assertSame(list, ListUtils.defaultIfNull(list, Collections.<Long>emptyList()));
70      }
71  
72      @Test
73      public void testEmptyIfNull() {
74          assertTrue(ListUtils.emptyIfNull(null).isEmpty());
75  
76          final List<Long> list = new ArrayList<>();
77          assertSame(list, ListUtils.emptyIfNull(list));
78      }
79  
80      @Test
81      public void testEquals() {
82          final Collection<String> data = Arrays.asList("a", "b", "c");
83  
84          final List<String> list1 = new ArrayList<>(data);
85          final List<String> list2 = new ArrayList<>(data);
86  
87          assertEquals(list1, list2);
88          assertTrue(ListUtils.isEqualList(list1, list2));
89          list1.clear();
90          assertFalse(ListUtils.isEqualList(list1, list2));
91          assertFalse(ListUtils.isEqualList(list1, null));
92          assertFalse(ListUtils.isEqualList(null, list2));
93          assertTrue(ListUtils.isEqualList(null, null));
94  
95          list2.clear();
96          list1.add("a");
97          list2.add("b");
98          assertFalse(ListUtils.isEqualList(list1, list2));
99  
100         list1.add("b");
101         list2.add("a");
102         assertFalse(ListUtils.isEqualList(list1, list2));
103     }
104 
105     @Test
106     public void testGetFirst() {
107         assertEquals(a, ListUtils.getFirst(fullList));
108         assertThrows(NullPointerException.class, () -> ListUtils.getFirst(null));
109         assertThrows(IndexOutOfBoundsException.class, () -> ListUtils.getFirst(new ArrayList<>()));
110     }
111 
112     @Test
113     public void testGetLast() {
114         assertEquals(e, ListUtils.getLast(fullList));
115         assertThrows(NullPointerException.class, () -> ListUtils.getFirst(null));
116         assertThrows(IndexOutOfBoundsException.class, () -> ListUtils.getFirst(new ArrayList<>()));
117     }
118 
119     @Test
120     public void testHashCode() {
121         final Collection<String> data = Arrays.asList("a", "b", "c");
122 
123         final List<String> list1 = new ArrayList<>(data);
124         final List<String> list2 = new ArrayList<>(data);
125 
126         assertEquals(list1.hashCode(), list2.hashCode());
127         assertEquals(list1.hashCode(), ListUtils.hashCodeForList(list1));
128         assertEquals(list2.hashCode(), ListUtils.hashCodeForList(list2));
129         assertEquals(ListUtils.hashCodeForList(list1), ListUtils.hashCodeForList(list2));
130         list1.clear();
131         assertNotEquals(ListUtils.hashCodeForList(list1), ListUtils.hashCodeForList(list2));
132         assertEquals(0, ListUtils.hashCodeForList(null));
133 
134         list1.add(null);
135         assertEquals(31, ListUtils.hashCodeForList(list1));
136     }
137 
138     /**
139      * Tests the {@code indexOf} method in {@code ListUtils} class.
140      */
141     @Test
142     public void testIndexOf() {
143         Predicate<String> testPredicate = EqualPredicate.equalPredicate("d");
144         int index = ListUtils.indexOf(fullList, testPredicate);
145         assertEquals(d, fullList.get(index));
146 
147         testPredicate = EqualPredicate.equalPredicate("de");
148         index = ListUtils.indexOf(fullList, testPredicate);
149         assertEquals(index, -1);
150 
151         assertEquals(ListUtils.indexOf(null, testPredicate), -1);
152         assertEquals(ListUtils.indexOf(fullList, null), -1);
153     }
154 
155     /**
156      * Tests intersecting a non-empty list with an empty list.
157      */
158     @Test
159     public void testIntersectEmptyWithEmptyList() {
160         final List<?> empty = Collections.EMPTY_LIST;
161         assertTrue(ListUtils.intersection(empty, empty).isEmpty(), "result not empty");
162     }
163 
164     /**
165      * Tests intersecting two lists in different orders.
166      */
167     @Test
168     public void testIntersectionOrderInsensitivity() {
169         final List<String> one = new ArrayList<>();
170         final List<String> two = new ArrayList<>();
171         one.add("a");
172         one.add("b");
173         two.add("a");
174         two.add("a");
175         two.add("b");
176         two.add("b");
177         assertEquals(ListUtils.intersection(one, two), ListUtils.intersection(two, one));
178     }
179 
180     /**
181      * Tests intersecting a non-empty list with a subset of itself.
182      */
183     @Test
184     public void testIntersectListWithNoOverlapAndDifferentTypes() {
185         @SuppressWarnings("boxing")
186         final List<Integer> other = Arrays.asList(1, 23);
187         assertTrue(ListUtils.intersection(fullList, other).isEmpty());
188     }
189 
190     /**
191      * Tests intersecting a non-empty list with itself.
192      */
193     @Test
194     public void testIntersectListWithSelf() {
195         assertEquals(fullList, ListUtils.intersection(fullList, fullList));
196     }
197 
198     /**
199      * Tests intersecting a non-empty list with a subset of itself.
200      */
201     @Test
202     public void testIntersectNonEmptySubset() {
203         // create a copy
204         final List<String> other = new ArrayList<>(fullList);
205 
206         // remove a few items
207         assertNotNull(other.remove(0));
208         assertNotNull(other.remove(1));
209 
210         // make sure the intersection is equal to the copy
211         assertEquals(other, ListUtils.intersection(fullList, other));
212     }
213 
214     /**
215      * Tests intersecting a non-empty list with an empty list.
216      */
217     @Test
218     public void testIntersectNonEmptyWithEmptyList() {
219         final List<String> empty = Collections.<String>emptyList();
220         assertTrue(ListUtils.intersection(empty, fullList).isEmpty(), "result not empty");
221     }
222 
223     @Test
224     public void testLazyFactoryList() {
225         final List<Integer> list = ListUtils.lazyList(new ArrayList<>(), new Factory<Integer>() {
226 
227             private int index;
228 
229             @Override
230             public Integer create() {
231                 index++;
232                 return Integer.valueOf(index);
233             }
234         });
235 
236         assertNotNull(list.get(5));
237         assertEquals(6, list.size());
238 
239         assertNotNull(list.get(5));
240         assertEquals(6, list.size());
241     }
242 
243     @Test
244     public void testLazyTransformerList() {
245         final List<Integer> offsets = Arrays.asList(3, 5, 1, 5, 3, 6);
246         final List<Integer> list = ListUtils.lazyList(new ArrayList<>(), new Transformer<Integer, Integer>() {
247 
248             private int index;
249 
250             @Override
251             public Integer transform(final Integer input) {
252                 return offsets.get(input) + index++;
253             }
254 
255         });
256 
257         assertNotNull(list.get(5));
258         assertEquals(6, list.size());
259 
260         assertNotNull(list.get(5));
261         assertEquals(6, list.size());
262     }
263 
264     @Test
265     @SuppressWarnings("boxing") // OK in test code
266     public void testLongestCommonSubsequence() {
267         assertThrows(NullPointerException.class, () -> ListUtils.longestCommonSubsequence((List<?>) null, null), "failed to check for null argument");
268         assertThrows(NullPointerException.class, () -> ListUtils.longestCommonSubsequence(Arrays.asList('A'), null), "failed to check for null argument");
269         assertThrows(NullPointerException.class, () -> ListUtils.longestCommonSubsequence(null, Arrays.asList('A')), "failed to check for null argument");
270         @SuppressWarnings("unchecked")
271         List<Character> lcs = ListUtils.longestCommonSubsequence(Collections.EMPTY_LIST, Collections.EMPTY_LIST);
272         assertEquals(0, lcs.size());
273 
274         final List<Character> list1 = Arrays.asList('B', 'A', 'N', 'A', 'N', 'A');
275         final List<Character> list2 = Arrays.asList('A', 'N', 'A', 'N', 'A', 'S');
276         lcs = ListUtils.longestCommonSubsequence(list1, list2);
277 
278         List<Character> expected = Arrays.asList('A', 'N', 'A', 'N', 'A');
279         assertEquals(expected, lcs);
280 
281         final List<Character> list3 = Arrays.asList('A', 'T', 'A', 'N', 'A');
282         lcs = ListUtils.longestCommonSubsequence(list1, list3);
283 
284         expected = Arrays.asList('A', 'A', 'N', 'A');
285         assertEquals(expected, lcs);
286 
287         final List<Character> listZorro = Arrays.asList('Z', 'O', 'R', 'R', 'O');
288         lcs = ListUtils.longestCommonSubsequence(list1, listZorro);
289 
290         assertTrue(lcs.isEmpty());
291     }
292 
293     @Test
294     public void testLongestCommonSubsequenceWithString() {
295         assertThrows(NullPointerException.class, () -> ListUtils.longestCommonSubsequence((String) null, null), "failed to check for null argument");
296         assertThrows(NullPointerException.class, () -> ListUtils.longestCommonSubsequence("A", null), "failed to check for null argument");
297         assertThrows(NullPointerException.class, () -> ListUtils.longestCommonSubsequence(null, "A"), "failed to check for null argument");
298         String lcs = ListUtils.longestCommonSubsequence(StringUtils.EMPTY, StringUtils.EMPTY);
299         assertEquals(0, lcs.length());
300 
301         final String banana = "BANANA";
302         final String ananas = "ANANAS";
303         lcs = ListUtils.longestCommonSubsequence(banana, ananas);
304 
305         assertEquals("ANANA", lcs);
306 
307         final String atana = "ATANA";
308         lcs = ListUtils.longestCommonSubsequence(banana, atana);
309 
310         assertEquals("AANA", lcs);
311 
312         final String zorro = "ZORRO";
313         lcs = ListUtils.longestCommonSubsequence(banana, zorro);
314 
315         assertEquals(0, lcs.length());
316     }
317 
318     @Test
319     @SuppressWarnings("boxing") // OK in test code
320     public void testPartition() {
321         final List<Integer> strings = new ArrayList<>();
322         for (int i = 0; i <= 6; i++) {
323             strings.add(i);
324         }
325 
326         final List<List<Integer>> partition = ListUtils.partition(strings, 3);
327 
328         assertNotNull(partition);
329         assertEquals(3, partition.size());
330         assertEquals(1, partition.get(2).size());
331 
332         assertThrows(IndexOutOfBoundsException.class, () -> partition.get(-1), "Index -1 must not be negative");
333         assertThrows(IndexOutOfBoundsException.class, () -> partition.get(3), "Index " + 3 + " must be less than size " + partition.size());
334         assertThrows(NullPointerException.class, () -> ListUtils.partition(null, 3), "failed to check for null argument");
335         assertThrows(IllegalArgumentException.class, () -> ListUtils.partition(strings, 0), "failed to check for size argument");
336         assertThrows(IllegalArgumentException.class, () -> ListUtils.partition(strings, -10), "failed to check for size argument");
337         final List<List<Integer>> partitionMax = ListUtils.partition(strings, Integer.MAX_VALUE);
338         assertEquals(1, partitionMax.size());
339         assertEquals(strings.size(), partitionMax.get(0).size());
340         assertEquals(strings, partitionMax.get(0));
341     }
342 
343     @Test
344     public void testPredicatedList() {
345         final Predicate<Object> predicate = String.class::isInstance;
346         final List<Object> list = ListUtils.predicatedList(new ArrayList<>(), predicate);
347         assertInstanceOf(PredicatedList.class, list, "returned object should be a PredicatedList");
348         assertThrows(NullPointerException.class, () -> ListUtils.predicatedList(new ArrayList<>(), null),
349                 "Expecting IllegalArgumentException for null predicate.");
350         assertThrows(NullPointerException.class, () -> ListUtils.predicatedList(null, predicate), "Expecting IllegalArgumentException for null list.");
351     }
352 
353     @Test
354     public void testRemoveAll() {
355         final List<String> sub = new ArrayList<>();
356         sub.add(a);
357         sub.add(b);
358         sub.add(x);
359 
360         final List<String> remainder = ListUtils.removeAll(fullList, sub);
361         assertEquals(3, remainder.size());
362         fullList.removeAll(sub);
363         assertEquals(remainder, fullList);
364 
365         assertThrows(NullPointerException.class, () -> ListUtils.removeAll(null, null),
366                 "expecting NullPointerException");
367 
368         assertThrows(NullPointerException.class, () -> ListUtils.removeAll(null, new ArrayList<>()),
369                 "expecting NullPointerException");
370 
371         assertThrows(NullPointerException.class, () -> ListUtils.removeAll(new ArrayList<>(), null),
372                 "expecting NullPointerException");
373     }
374 
375     @Test
376     public void testRetainAll() {
377         final List<String> sub = new ArrayList<>();
378         sub.add(a);
379         sub.add(b);
380         sub.add(x);
381 
382         final List<String> retained = ListUtils.retainAll(fullList, sub);
383         assertEquals(2, retained.size());
384         sub.remove(x);
385         assertEquals(retained, sub);
386         fullList.retainAll(sub);
387         assertEquals(retained, fullList);
388 
389         assertThrows(NullPointerException.class, () -> ListUtils.retainAll(null, null),
390                 "expecting NullPointerException");
391     }
392 
393     @Test
394     @SuppressWarnings("boxing") // OK in test code
395     public void testSelect() {
396         final List<Integer> list = new ArrayList<>();
397         list.add(1);
398         list.add(2);
399         list.add(3);
400         list.add(4);
401         // Ensure that the collection is the input type or a super type
402         final List<Integer> output1 = ListUtils.select(list, EQUALS_TWO);
403         final List<Number> output2 = ListUtils.<Number>select(list, EQUALS_TWO);
404         final HashSet<Number> output3 = CollectionUtils.select(list, EQUALS_TWO, new HashSet<>());
405         assertTrue(CollectionUtils.isEqualCollection(output1, output3));
406         assertEquals(4, list.size());
407         assertEquals(1, output1.size());
408         assertEquals(2, output2.iterator().next());
409     }
410 
411     @Test
412     @SuppressWarnings("boxing") // OK in test code
413     public void testSelectRejected() {
414         final List<Long> list = new ArrayList<>();
415         list.add(1L);
416         list.add(2L);
417         list.add(3L);
418         list.add(4L);
419         final List<Long> output1 = ListUtils.selectRejected(list, EQUALS_TWO);
420         final List<? extends Number> output2 = ListUtils.selectRejected(list, EQUALS_TWO);
421         final HashSet<Number> output3 = CollectionUtils.selectRejected(list, EQUALS_TWO, new HashSet<>());
422         assertTrue(CollectionUtils.isEqualCollection(output1, output2));
423         assertTrue(CollectionUtils.isEqualCollection(output1, output3));
424         assertEquals(4, list.size());
425         assertEquals(3, output1.size());
426         assertTrue(output1.contains(1L));
427         assertTrue(output1.contains(3L));
428         assertTrue(output1.contains(4L));
429     }
430 
431     @Test
432     public void testSubtract() {
433         final List<String> list = new ArrayList<>();
434         list.add(a);
435         list.add(b);
436         list.add(a);
437         list.add(x);
438 
439         final List<String> sub = new ArrayList<>();
440         sub.add(a);
441 
442         final List<String> result = ListUtils.subtract(list, sub);
443         assertEquals(3, result.size());
444 
445         final List<String> expected = new ArrayList<>();
446         expected.add(b);
447         expected.add(a);
448         expected.add(x);
449 
450         assertEquals(expected, result);
451 
452         assertThrows(NullPointerException.class, () -> ListUtils.subtract(list, null),
453                 "expecting NullPointerException");
454     }
455 
456     @Test
457     public void testSubtractNullElement() {
458         final List<String> list = new ArrayList<>();
459         list.add(a);
460         list.add(null);
461         list.add(null);
462         list.add(x);
463 
464         final List<String> sub = new ArrayList<>();
465         sub.add(null);
466 
467         final List<String> result = ListUtils.subtract(list, sub);
468         assertEquals(3, result.size());
469 
470         final List<String> expected = new ArrayList<>();
471         expected.add(a);
472         expected.add(null);
473         expected.add(x);
474 
475         assertEquals(expected, result);
476     }
477 
478     @Test
479     public void testSum() {
480         final List<String> list1 = new ArrayList<>();
481         list1.add(a);
482         final List<String> list2 = new ArrayList<>();
483         list2.add(b);
484         final List<String> expected1 = new ArrayList<>();
485         expected1.add(a);
486         expected1.add(b);
487         final List<String> result1 = ListUtils.sum(list1, list2);
488         assertEquals(2, result1.size());
489         assertEquals(expected1, result1);
490     }
491 
492     @Test
493     public void testUnion() {
494         final List<String> list1 = new ArrayList<>();
495         list1.add(a);
496         final List<String> list2 = new ArrayList<>();
497         list2.add(b);
498         final List<String> result1 = ListUtils.union(list1, list2);
499         final List<String> expected1 = new ArrayList<>();
500         expected1.add(a);
501         expected1.add(b);
502         assertEquals(2, result1.size());
503         assertEquals(expected1, result1);
504 
505         final List<String> list3 = new ArrayList<>();
506         list3.add(a);
507         final List<String> result2 = ListUtils.union(list1, list3);
508         final List<String> expected2 = new ArrayList<>();
509         expected2.add(a);
510         expected2.add(a);
511         assertEquals(2, result1.size());
512         assertEquals(expected2, result2);
513 
514         list1.add(null);
515         final List<String> result3 = ListUtils.union(list1, list2);
516         final List<String> expected3 = new ArrayList<>();
517         expected3.add(a);
518         expected3.add(null);
519         expected3.add(b);
520         assertEquals(3, result3.size());
521         assertEquals(expected3, result3);
522 
523         list2.add(null);
524         final List<String> result4 = ListUtils.union(list1, list2);
525         final List<String> expected4 = new ArrayList<>();
526         expected4.add(a);
527         expected4.add(null);
528         expected4.add(b);
529         expected4.add(null);
530         assertEquals(4, result4.size());
531         assertEquals(expected4, result4);
532     }
533 }