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