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 java.util.AbstractList;
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.Collections;
23 import java.util.HashSet;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Objects;
27
28 import org.apache.commons.collections4.bag.HashBag;
29 import org.apache.commons.collections4.functors.DefaultEquator;
30 import org.apache.commons.collections4.list.FixedSizeList;
31 import org.apache.commons.collections4.list.LazyList;
32 import org.apache.commons.collections4.list.PredicatedList;
33 import org.apache.commons.collections4.list.TransformedList;
34 import org.apache.commons.collections4.list.UnmodifiableList;
35 import org.apache.commons.collections4.sequence.CommandVisitor;
36 import org.apache.commons.collections4.sequence.EditScript;
37 import org.apache.commons.collections4.sequence.SequencesComparator;
38
39 /**
40 * Provides utility methods and decorators for {@link List} instances.
41 *
42 * @since 1.0
43 */
44 public class ListUtils {
45
46 /**
47 * A simple wrapper to use a CharSequence as List.
48 */
49 private static final class CharSequenceAsList extends AbstractList<Character> {
50 private final CharSequence sequence;
51
52 CharSequenceAsList(final CharSequence sequence) {
53 this.sequence = sequence;
54 }
55
56 @Override
57 public Character get(final int index) {
58 return Character.valueOf(sequence.charAt(index));
59 }
60
61 @Override
62 public int size() {
63 return sequence.length();
64 }
65 }
66
67 /**
68 * A helper class used to construct the longest common subsequence.
69 */
70 private static final class LcsVisitor<E> implements CommandVisitor<E> {
71 private final ArrayList<E> sequence;
72
73 LcsVisitor() {
74 sequence = new ArrayList<>();
75 }
76
77 public List<E> getSubSequence() {
78 return sequence;
79 }
80
81 @Override
82 public void visitDeleteCommand(final E object) {
83 // noop
84 }
85
86 @Override
87 public void visitInsertCommand(final E object) {
88 // noop
89 }
90
91 @Override
92 public void visitKeepCommand(final E object) {
93 sequence.add(object);
94 }
95 }
96
97 /**
98 * Provides a partition view on a {@link List}.
99 * @since 4.0
100 */
101 private static final class Partition<T> extends AbstractList<List<T>> {
102 private final List<T> list;
103 private final int size;
104
105 private Partition(final List<T> list, final int size) {
106 this.list = list;
107 this.size = size;
108 }
109
110 @Override
111 public List<T> get(final int index) {
112 final int listSize = size();
113 if (index < 0) {
114 throw new IndexOutOfBoundsException("Index " + index + " must not be negative");
115 }
116 if (index >= listSize) {
117 throw new IndexOutOfBoundsException("Index " + index + " must be less than size " +
118 listSize);
119 }
120 final int start = index * size;
121 final int end = Math.min(start + size, list.size());
122 return list.subList(start, end);
123 }
124
125 @Override
126 public boolean isEmpty() {
127 return list.isEmpty();
128 }
129
130 @Override
131 public int size() {
132 return (int) Math.ceil((double) list.size() / (double) size);
133 }
134 }
135
136 /**
137 * Returns either the passed in list, or if the list is {@code null},
138 * the value of {@code defaultList}.
139 *
140 * @param <T> the element type
141 * @param list the list, possibly {@code null}
142 * @param defaultList the returned values if list is {@code null}
143 * @return an empty list if the argument is {@code null}
144 * @since 4.0
145 */
146 public static <T> List<T> defaultIfNull(final List<T> list, final List<T> defaultList) {
147 return list == null ? defaultList : list;
148 }
149
150 /**
151 * Returns an immutable empty list if the argument is {@code null},
152 * or the argument itself otherwise.
153 *
154 * @param <T> the element type
155 * @param list the list, possibly {@code null}
156 * @return an empty list if the argument is {@code null}
157 */
158 public static <T> List<T> emptyIfNull(final List<T> list) {
159 return list == null ? Collections.<T>emptyList() : list;
160 }
161
162 /**
163 * Returns a fixed-sized list backed by the given list.
164 * Elements may not be added or removed from the returned list, but
165 * existing elements can be changed (for instance, via the
166 * {@link List#set(int, Object)} method).
167 *
168 * @param <E> the element type
169 * @param list the list whose size to fix, must not be null
170 * @return a fixed-size list backed by that list
171 * @throws NullPointerException if the List is null
172 */
173 public static <E> List<E> fixedSizeList(final List<E> list) {
174 return FixedSizeList.fixedSizeList(list);
175 }
176
177 /**
178 * Gets the first element of a list.
179 * <p>
180 * Shorthand for {@code list.get(0)}
181 * </p>
182 *
183 * @param <T> The list type.
184 * @param list The list.
185 * @return the first element of a list.
186 * @see List#get(int)
187 * @since 4.5.0-M1
188 */
189 public static <T> T getFirst(final List<T> list) {
190 return Objects.requireNonNull(list, "list").get(0);
191 }
192
193 /**
194 * Gets the last element of a list.
195 * <p>
196 * Shorthand for {@code list.get(list.size() - 1)}
197 * </p>
198 *
199 * @param <T> The list type.
200 * @param list The list.
201 * @return the last element of a list.
202 * @see List#get(int)
203 * @since 4.5.0-M1
204 */
205 public static <T> T getLast(final List<T> list) {
206 return Objects.requireNonNull(list, "list").get(list.size() - 1);
207 }
208
209 /**
210 * Generates a hash code using the algorithm specified in
211 * {@link java.util.List#hashCode()}.
212 * <p>
213 * This method is useful for implementing {@code List} when you cannot
214 * extend AbstractList. The method takes Collection instances to enable other
215 * collection types to use the List implementation algorithm.
216 * </p>
217 *
218 * @see java.util.List#hashCode()
219 * @param list the list to generate the hashCode for, may be null
220 * @return the hash code
221 */
222 public static int hashCodeForList(final Collection<?> list) {
223 if (list == null) {
224 return 0;
225 }
226 int hashCode = 1;
227
228 for (final Object obj : list) {
229 hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
230 }
231 return hashCode;
232 }
233
234 /**
235 * Finds the first index in the given List which matches the given predicate.
236 * <p>
237 * If the input List or predicate is null, or no element of the List
238 * matches the predicate, -1 is returned.
239 * </p>
240 *
241 * @param <E> the element type
242 * @param list the List to search, may be null
243 * @param predicate the predicate to use, may be null
244 * @return the first index of an Object in the List which matches the predicate or -1 if none could be found
245 */
246 public static <E> int indexOf(final List<E> list, final Predicate<E> predicate) {
247 if (list != null && predicate != null) {
248 for (int i = 0; i < list.size(); i++) {
249 final E item = list.get(i);
250 if (predicate.test(item)) {
251 return i;
252 }
253 }
254 }
255 return CollectionUtils.INDEX_NOT_FOUND;
256 }
257
258 /**
259 * Returns a new list containing all elements that are contained in
260 * both given lists.
261 *
262 * @param <E> the element type
263 * @param list1 the first list
264 * @param list2 the second list
265 * @return the intersection of those two lists
266 * @throws NullPointerException if either list is null
267 */
268 public static <E> List<E> intersection(final List<? extends E> list1, final List<? extends E> list2) {
269 final List<E> result = new ArrayList<>();
270
271 List<? extends E> smaller = list1;
272 List<? extends E> larger = list2;
273 if (list1.size() > list2.size()) {
274 smaller = list2;
275 larger = list1;
276 }
277
278 final HashSet<E> hashSet = new HashSet<>(smaller);
279
280 for (final E e : larger) {
281 if (hashSet.contains(e)) {
282 result.add(e);
283 hashSet.remove(e);
284 }
285 }
286 return result;
287 }
288
289 /**
290 * Tests two lists for value-equality as per the equality contract in
291 * {@link java.util.List#equals(Object)}.
292 * <p>
293 * This method is useful for implementing {@code List} when you cannot
294 * extend AbstractList. The method takes Collection instances to enable other
295 * collection types to use the List implementation algorithm.
296 * </p>
297 * <p>
298 * The relevant text (slightly paraphrased as this is a static method) is:
299 * </p>
300 * <blockquote>
301 * Compares the two list objects for equality. Returns
302 * {@code true} if and only if both
303 * lists have the same size, and all corresponding pairs of elements in
304 * the two lists are <em>equal</em>. (Two elements {@code e1} and
305 * {@code e2} are <em>equal</em> if {@code (e1==null ? e2==null :
306 * e1.equals(e2))}.) In other words, two lists are defined to be
307 * equal if they contain the same elements in the same order. This
308 * definition ensures that the equals method works properly across
309 * different implementations of the {@code List} interface.
310 * </blockquote>
311 * <p>
312 * <strong>Note:</strong> The behavior of this method is undefined if the lists are
313 * modified during the equals comparison.
314 * </p>
315 *
316 * @see java.util.List
317 * @param list1 the first list, may be null
318 * @param list2 the second list, may be null
319 * @return whether the lists are equal by value comparison
320 */
321 public static boolean isEqualList(final Collection<?> list1, final Collection<?> list2) {
322 if (list1 == list2) {
323 return true;
324 }
325 if (list1 == null || list2 == null || list1.size() != list2.size()) {
326 return false;
327 }
328
329 final Iterator<?> it1 = list1.iterator();
330 final Iterator<?> it2 = list2.iterator();
331
332 while (it1.hasNext() && it2.hasNext()) {
333 final Object obj1 = it1.next();
334 final Object obj2 = it2.next();
335
336 if (!Objects.equals(obj1, obj2)) {
337 return false;
338 }
339 }
340
341 return !(it1.hasNext() || it2.hasNext());
342 }
343
344 /**
345 * Returns a "lazy" list whose elements will be created on demand.
346 * <p>
347 * When the index passed to the returned list's {@link List#get(int) get}
348 * method is greater than the list's size, then the factory will be used
349 * to create a new object and that object will be inserted at that index.
350 * </p>
351 * <p>
352 * For instance:
353 * </p>
354 * <pre>
355 * Factory<Date> factory = new Factory<Date>() {
356 * public Date create() {
357 * return new Date();
358 * }
359 * }
360 * List<Date> lazy = ListUtils.lazyList(new ArrayList<Date>(), factory);
361 * Date date = lazy.get(3);
362 * </pre>
363 * <p>
364 * After the above code is executed, {@code date} will refer to
365 * a new {@code Date} instance. Furthermore, that {@code Date}
366 * instance is the fourth element in the list. The first, second,
367 * and third element are all set to {@code null}.
368 * </p>
369 *
370 * @param <E> the element type
371 * @param list the list to make lazy, must not be null
372 * @param factory the factory for creating new objects, must not be null
373 * @return a lazy list backed by the given list
374 * @throws NullPointerException if the List or Factory is null
375 */
376 public static <E> List<E> lazyList(final List<E> list, final Factory<? extends E> factory) {
377 return LazyList.lazyList(list, factory);
378 }
379
380 /**
381 * Returns a "lazy" list whose elements will be created on demand.
382 * <p>
383 * When the index passed to the returned list's {@link List#get(int) get}
384 * method is greater than the list's size, then the transformer will be used
385 * to create a new object and that object will be inserted at that index.
386 * </p>
387 * <p>
388 * For instance:
389 * </p>
390 * <pre>
391 * List<Integer> hours = Arrays.asList(7, 5, 8, 2);
392 * Transformer<Integer,Date> transformer = input -> LocalDateTime.now().withHour(hours.get(input));
393 * List<LocalDateTime> lazy = ListUtils.lazyList(new ArrayList<LocalDateTime>(), transformer);
394 * Date date = lazy.get(3);
395 * </pre>
396 * <p>
397 * After the above code is executed, {@code date} will refer to
398 * a new {@code Date} instance. Furthermore, that {@code Date}
399 * instance is the fourth element in the list. The first, second,
400 * and third element are all set to {@code null}.
401 * </p>
402 *
403 * @param <E> the element type
404 * @param list the list to make lazy, must not be null
405 * @param transformer the transformer for creating new objects, must not be null
406 * @return a lazy list backed by the given list
407 * @throws NullPointerException if the List or Transformer is null
408 */
409 public static <E> List<E> lazyList(final List<E> list, final Transformer<Integer, ? extends E> transformer) {
410 return LazyList.lazyList(list, transformer);
411 }
412
413 /**
414 * Returns the longest common subsequence (LCS) of two {@link CharSequence} objects.
415 * <p>
416 * This is a convenience method for using {@link #longestCommonSubsequence(List, List)}
417 * with {@link CharSequence} instances.
418 * </p>
419 *
420 * @param charSequenceA the first sequence
421 * @param charSequenceB the second sequence
422 * @return the longest common subsequence as {@link String}
423 * @throws NullPointerException if either sequence is {@code null}
424 * @since 4.0
425 */
426 public static String longestCommonSubsequence(final CharSequence charSequenceA, final CharSequence charSequenceB) {
427 Objects.requireNonNull(charSequenceA, "charSequenceA");
428 Objects.requireNonNull(charSequenceB, "charSequenceB");
429 final List<Character> lcs = longestCommonSubsequence(new CharSequenceAsList(charSequenceA),
430 new CharSequenceAsList(charSequenceB));
431 final StringBuilder sb = new StringBuilder();
432 for (final Character ch : lcs) {
433 sb.append(ch);
434 }
435 return sb.toString();
436 }
437
438 /**
439 * Returns the longest common subsequence (LCS) of two sequences (lists).
440 *
441 * @param <E> the element type
442 * @param a the first list
443 * @param b the second list
444 * @return the longest common subsequence
445 * @throws NullPointerException if either list is {@code null}
446 * @since 4.0
447 */
448 public static <E> List<E> longestCommonSubsequence(final List<E> a, final List<E> b) {
449 return longestCommonSubsequence(a, b, DefaultEquator.defaultEquator());
450 }
451
452 /**
453 * Returns the longest common subsequence (LCS) of two sequences (lists).
454 *
455 * @param <E> the element type
456 * @param listA the first list
457 * @param listB the second list
458 * @param equator the equator used to test object equality
459 * @return the longest common subsequence
460 * @throws NullPointerException if either list or the equator is {@code null}
461 * @since 4.0
462 */
463 public static <E> List<E> longestCommonSubsequence(final List<E> listA, final List<E> listB,
464 final Equator<? super E> equator) {
465 Objects.requireNonNull(listA, "listA");
466 Objects.requireNonNull(listB, "listB");
467 Objects.requireNonNull(equator, "equator");
468
469 final SequencesComparator<E> comparator = new SequencesComparator<>(listA, listB, equator);
470 final EditScript<E> script = comparator.getScript();
471 final LcsVisitor<E> visitor = new LcsVisitor<>();
472 script.visit(visitor);
473 return visitor.getSubSequence();
474 }
475
476 /**
477 * Returns consecutive {@link List#subList(int, int) sublists} of a
478 * list, each of the same size (the final list may be smaller). For example,
479 * partitioning a list containing {@code [a, b, c, d, e]} with a partition
480 * size of 3 yields {@code [[a, b, c], [d, e]]} -- an outer list containing
481 * two inner lists of three and two elements, all in the original order.
482 * <p>
483 * The outer list is unmodifiable, but reflects the latest state of the
484 * source list. The inner lists are sublist views of the original list,
485 * produced on demand using {@link List#subList(int, int)}, and are subject
486 * to all the usual caveats about modification as explained in that API.
487 * </p>
488 * <p>
489 * Adapted from https://github.com/google/guava
490 * </p>
491 *
492 * @param <T> the element type
493 * @param list the list to return consecutive sublists of
494 * @param size the desired size of each sublist (the last may be smaller)
495 * @return a list of consecutive sublists
496 * @throws NullPointerException if list is null
497 * @throws IllegalArgumentException if size is not strictly positive
498 * @since 4.0
499 */
500 public static <T> List<List<T>> partition(final List<T> list, final int size) {
501 Objects.requireNonNull(list, "list");
502 if (size <= 0) {
503 throw new IllegalArgumentException("Size must be greater than 0");
504 }
505 return new Partition<>(list, size);
506 }
507
508 /**
509 * Returns a predicated (validating) list backed by the given list.
510 * <p>
511 * Only objects that pass the test in the given predicate can be added to the list.
512 * Trying to add an invalid object results in an IllegalArgumentException.
513 * It is important not to use the original list after invoking this method,
514 * as it is a backdoor for adding invalid objects.
515 * </p>
516 *
517 * @param <E> the element type
518 * @param list the list to predicate, must not be null
519 * @param predicate the predicate for the list, must not be null
520 * @return a predicated list backed by the given list
521 * @throws NullPointerException if the List or Predicate is null
522 */
523 public static <E> List<E> predicatedList(final List<E> list, final Predicate<E> predicate) {
524 return PredicatedList.predicatedList(list, predicate);
525 }
526
527 /**
528 * Removes the elements in {@code remove} from {@code collection}. That is, this
529 * method returns a list containing all the elements in {@code collection}
530 * that are not in {@code remove}. The cardinality of an element {@code e}
531 * in the returned collection is the same as the cardinality of {@code e}
532 * in {@code collection} unless {@code remove} contains {@code e}, in which
533 * case the cardinality is zero. This method is useful if you do not wish to modify
534 * {@code collection} and thus cannot call {@code collection.removeAll(remove);}.
535 * <p>
536 * This implementation iterates over {@code collection}, checking each element in
537 * turn to see if it's contained in {@code remove}. If it's not contained, it's added
538 * to the returned list. As a consequence, it is advised to use a collection type for
539 * {@code remove} that provides a fast (for example O(1)) implementation of
540 * {@link Collection#contains(Object)}.
541 * </p>
542 *
543 * @param <E> the element type
544 * @param collection the collection from which items are removed (in the returned collection)
545 * @param remove the items to be removed from the returned {@code collection}
546 * @return a {@code List} containing all the elements of {@code c} except
547 * any elements that also occur in {@code remove}.
548 * @throws NullPointerException if either parameter is null
549 * @since 3.2
550 */
551 public static <E> List<E> removeAll(final Collection<E> collection, final Collection<?> remove) {
552 Objects.requireNonNull(collection, "collection");
553 Objects.requireNonNull(remove, "remove");
554 final List<E> list = new ArrayList<>();
555 for (final E obj : collection) {
556 if (!remove.contains(obj)) {
557 list.add(obj);
558 }
559 }
560 return list;
561 }
562
563 /**
564 * Returns a List containing all the elements in {@code collection}
565 * that are also in {@code retain}. The cardinality of an element {@code e}
566 * in the returned list is the same as the cardinality of {@code e}
567 * in {@code collection} unless {@code retain} does not contain {@code e}, in which
568 * case the cardinality is zero. This method is useful if you do not wish to modify
569 * the collection {@code c} and thus cannot call {@code collection.retainAll(retain);}.
570 * <p>
571 * This implementation iterates over {@code collection}, checking each element in
572 * turn to see if it's contained in {@code retain}. If it's contained, it's added
573 * to the returned list. As a consequence, it is advised to use a collection type for
574 * {@code retain} that provides a fast (for example O(1)) implementation of
575 * {@link Collection#contains(Object)}.
576 * </p>
577 *
578 * @param <E> the element type
579 * @param collection the collection whose contents are the target of the #retailAll operation
580 * @param retain the collection containing the elements to be retained in the returned collection
581 * @return a {@code List} containing all the elements of {@code c}
582 * that occur at least once in {@code retain}.
583 * @throws NullPointerException if either parameter is null
584 * @since 3.2
585 */
586 public static <E> List<E> retainAll(final Collection<E> collection, final Collection<?> retain) {
587 final List<E> list = new ArrayList<>(Math.min(collection.size(), retain.size()));
588
589 for (final E obj : collection) {
590 if (retain.contains(obj)) {
591 list.add(obj);
592 }
593 }
594 return list;
595 }
596
597 /**
598 * Selects all elements from input collection which match the given
599 * predicate into an output list.
600 * <p>
601 * A {@code null} predicate matches no elements.
602 * </p>
603 *
604 * @param <E> the element type
605 * @param inputCollection the collection to get the input from, may not be null
606 * @param predicate the predicate to use, may be null
607 * @return the elements matching the predicate (new list)
608 * @throws NullPointerException if the input list is null
609 * @since 4.0
610 * @see CollectionUtils#select(Iterable, Predicate)
611 */
612 public static <E> List<E> select(final Collection<? extends E> inputCollection,
613 final Predicate<? super E> predicate) {
614 return CollectionUtils.select(inputCollection, predicate, new ArrayList<>(inputCollection.size()));
615 }
616
617 /**
618 * Selects all elements from inputCollection which don't match the given
619 * predicate into an output collection.
620 * <p>
621 * If the input predicate is {@code null}, the result is an empty list.
622 * </p>
623 *
624 * @param <E> the element type
625 * @param inputCollection the collection to get the input from, may not be null
626 * @param predicate the predicate to use, may be null
627 * @return the elements <strong>not</strong> matching the predicate (new list)
628 * @throws NullPointerException if the input collection is null
629 * @since 4.0
630 * @see CollectionUtils#selectRejected(Iterable, Predicate)
631 */
632 public static <E> List<E> selectRejected(final Collection<? extends E> inputCollection,
633 final Predicate<? super E> predicate) {
634 return CollectionUtils.selectRejected(inputCollection, predicate, new ArrayList<>(inputCollection.size()));
635 }
636
637 /**
638 * Subtracts all elements in the second list from the first list,
639 * placing the results in a new list.
640 * <p>
641 * This differs from {@link List#removeAll(Collection)} in that
642 * cardinality is respected; if <Code>list1</Code> contains two
643 * occurrences of <Code>null</Code> and <Code>list2</Code> only
644 * contains one occurrence, then the returned list will still contain
645 * one occurrence.
646 * </p>
647 *
648 * @param <E> the element type
649 * @param list1 the list to subtract from
650 * @param list2 the list to subtract
651 * @return a new list containing the results
652 * @throws NullPointerException if either list is null
653 */
654 public static <E> List<E> subtract(final List<E> list1, final List<? extends E> list2) {
655 final ArrayList<E> result = new ArrayList<>();
656 final HashBag<E> bag = new HashBag<>(list2);
657 for (final E e : list1) {
658 if (!bag.remove(e, 1)) {
659 result.add(e);
660 }
661 }
662 return result;
663 }
664
665 /**
666 * Returns the sum of the given lists. This is their intersection
667 * subtracted from their union.
668 *
669 * @param <E> the element type
670 * @param list1 the first list
671 * @param list2 the second list
672 * @return a new list containing the sum of those lists
673 * @throws NullPointerException if either list is null
674 */
675 public static <E> List<E> sum(final List<? extends E> list1, final List<? extends E> list2) {
676 return subtract(union(list1, list2), intersection(list1, list2));
677 }
678
679 /**
680 * Returns a synchronized list backed by the given list.
681 * <p>
682 * You must manually synchronize on the returned list's iterator to
683 * avoid non-deterministic behavior:
684 * </p>
685 * <pre>
686 * List list = ListUtils.synchronizedList(myList);
687 * synchronized (list) {
688 * Iterator i = list.iterator();
689 * while (i.hasNext()) {
690 * process (i.next());
691 * }
692 * }
693 * </pre>
694 * <p>
695 * This method is just a wrapper for {@link Collections#synchronizedList(List)}.
696 * </p>
697 *
698 * @param <E> the element type
699 * @param list the list to synchronize, must not be null
700 * @return a synchronized list backed by the given list
701 * @throws NullPointerException if the list is null
702 */
703 public static <E> List<E> synchronizedList(final List<E> list) {
704 return Collections.synchronizedList(list);
705 }
706
707 /**
708 * Returns a transformed list backed by the given list.
709 * <p>
710 * This method returns a new list (decorating the specified list) that
711 * will transform any new entries added to it.
712 * Existing entries in the specified list will not be transformed.
713 * </p>
714 * <p>
715 * Each object is passed through the transformer as it is added to the
716 * List. It is important not to use the original list after invoking this
717 * method, as it is a backdoor for adding untransformed objects.
718 * </p>
719 * <p>
720 * Existing entries in the specified list will not be transformed.
721 * If you want that behavior, see {@link TransformedList#transformedList}.
722 * </p>
723 *
724 * @param <E> the element type
725 * @param list the list to predicate, must not be null
726 * @param transformer the transformer for the list, must not be null
727 * @return a transformed list backed by the given list
728 * @throws NullPointerException if the List or Transformer is null
729 */
730 public static <E> List<E> transformedList(final List<E> list,
731 final Transformer<? super E, ? extends E> transformer) {
732 return TransformedList.transformingList(list, transformer);
733 }
734
735 /**
736 * Returns a new list containing the second list appended to the
737 * first list. The {@link List#addAll(Collection)} operation is
738 * used to append the two given lists into a new list.
739 *
740 * @param <E> the element type
741 * @param list1 the first list
742 * @param list2 the second list
743 * @return a new list containing the union of those lists
744 * @throws NullPointerException if either list is null
745 */
746 public static <E> List<E> union(final List<? extends E> list1, final List<? extends E> list2) {
747 final ArrayList<E> result = new ArrayList<>(list1.size() + list2.size());
748 result.addAll(list1);
749 result.addAll(list2);
750 return result;
751 }
752
753 /**
754 * Returns an unmodifiable list backed by the given list.
755 * <p>
756 * This method uses the implementation in the decorators subpackage.
757 * </p>
758 *
759 * @param <E> the element type
760 * @param list the list to make unmodifiable, must not be null
761 * @return an unmodifiable list backed by the given list
762 * @throws NullPointerException if the list is null
763 */
764 public static <E> List<E> unmodifiableList(final List<? extends E> list) {
765 return UnmodifiableList.unmodifiableList(list);
766 }
767
768 /**
769 * Don't allow instances.
770 */
771 private ListUtils() {
772 // empty
773 }
774
775 }