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