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