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