Apache Commons logo Commons Collections

Release notes for version 4.0


Commons collections is a project to develop and maintain collection classes based on and inspired by the JDK collection framework. This version uses the generics features of Java 5 and is not compatible with earlier JDK versions.

The process of generifying an API is complex. For commons-collections, we have chosen to break the API in various ways. The aim behind this is to provide an API design that better suits generics. We have also removed all deprecated classes and fixed oddities in the previous API that we couldn't fix due to backwards compatibility restrictions.

As such, this release can not be considered to be a simple, drop-in, replacement for commons-collections. To help with the migration to this new version, the package has changed to "org.apache.commons.collections4", thus it is possible to have both commons-collections versions in the classpath.

These release notes will try to guide you in the process of upgrading, however you should remember that this is a new API based on the original, so some concepts have changed.

Compatibility

  • Java 5 or later is required
  • This release is not source or binary compatible with previous releases of Commons Collections. This includes releases from the 3.x branch as well as preceding alpha releases for 4.0 (see details of changes below)

Major changes since 3.2.1

  • Use of generics and other language features introduced in Java 5 (varargs, Iterable)
  • Removed deprecated classes / methods and features which are now supported by the JDK
  • Replaced Buffer interface with java.util.Queue
  • Added concept of split maps with respective interfaces Put / Get (see also package splitmap)
  • Added new Trie interface together with an implementation of a Patricia Trie

Removed Classes

  • Removed unused class "AbstractUntypedCollectionDecorator"
  • Removed "Buffer" interface and all its implementations and related classes. Replaced by "java.util.Queue", see also section [New classes]
    • PriorityBuffer: use either java.util.PriorityQueue or java.util.concurrent.PriorityBlockingQueue
    • SynchronizedBuffer: use the corresponding *BlockingQueue classes in java.util.concurrent
    • BoundedBuffer: use either ArrayBlockingBuffer(capacity) or LinkedBlockingBuffer(capacity) in java.util.concurrent
    • UnboundedFifoBuffer: use either java.util.LinkedList or java.util.concurrent.LinkedBlockingBuffer
  • Removed features now supported by the JDK or other Apache Commons libraries
    • FastArrayList: use java.util.concurrent.CopyOnWriteArrayList
    • FastHashMap: use java.util.concurrent.ConcurrentHashMap, but beware of null keys and values
    • FastTreeSet: no direct replacement, use ConcurrentHashMap or a synchronized TreeMap
    • IdentityMap: use java.util.IdentityHashMap
    • ExtendedProperties: use commons-configuration
    • Synchronized[List,Set,SortedSet]: use java.util.Collections.synchronized*()
    • Typed* decorators: use generics for type safety, or java.util.Collections.checked*()
    • [List,Set,Map]Utils.EMPTY_*: use the corresponding fields in java.util.Collections
  • Removed deprecated collection classes and methods

New Classes

  • CollectionSortedBag - decorates a SortedBag to make it comply with the Collection contract.
  • CollectionBag - decorates another Bag to make it comply with the Collection contract.
  • PushbackIterator - supports pushback of elements during iteration. Thanks to Andy Seaborne, Claude Warren.
  • PeekingIterator - supports one-element lookahead during iteration. Thanks to Andy Seaborne, Claude Warren.
  • CircularFifoQueue - analogous class to CircularFifoBuffer for the Queue interface
  • PredicatedQueue - analogous class to PredicatedBuffer
  • TransformedQueue - analogous class to TransformedBuffer
  • UnmodifiableQueue - analogous class to UnmodifiableBuffer
  • QueueUtils - analogous class to BufferUtils
  • PermutationIterator - generates unordered permutations of a collection. Thanks to Benoit Corne.
  • SequencesComparator - an implementation of Eugene Myers difference algorithm in package o.a.c.c.sequence. Thanks to Jordane Sarda.
  • LazyIteratorChain - a variant of IteratorChain which supports lazy initialization. Thanks to Jeff Rodriguez.
  • NodeListIterator - supports iteration over a org.w3c.dom.NodeList. Thanks to Thomas Vahrst.
  • CatchAndRethrowClosure - re-throws any checked exception as unchecked "FunctorException". Thanks to David J. M. Karlsen.
  • IndexedCollection - collection decorator which provides a map-like view on an existing collection. Thanks to Stephen Kestle.
  • DualLinkedHashBidiMap - bidi map implementation using LinkedHashMap instances. Thanks to Nathan Blomquist.
  • Equator - interface for testing object equality.
  • PassiveExpiringMap - map decorator which passively expires entries. Thanks to Elifarley Callado Coelho.
  • PatriciaTrie - PATRICIA trie implementation for the new Trie interface, together with Unmodifiable and Synchronized decorators. Thanks to Sam Berlin and Roger Kapsi.
  • ComparatorPredicate - predicate to compare objects against a fixed instance. Thanks to Rune Peter Bjørnstad.
  • Put / Get - interfaces for split maps
  • SplitMapUtils / splitmap.TransformedSplitMap - utilities and implementation for split maps

Enhancements

  • Added CollectionsUtils#matchesAll(Iterable, Predicate) to test if all elements of a collection match a given predicate.
  • ListUtils#longestCommonSubsequence(...) to get the longest common subsequence of arbitrary lists or CharSequences.
  • CollectionUtils#forAllButLastDo(Collection, Closure) and forAllButLastDo(Iterator, Closure). Thanks to J. Moldawski.
  • CollectionUtils#isEqualCollection(Collection, Collection, Equator). Thanks to Matt Lachman.
  • *Utils#emptyIfNull(*) methods in classes CollectionUtils, ListUtils, SetUtils and MapUtils. Thanks to Arman Sharif.
  • CollectionUtils#containsAll(Collection, Collection) with guaranteed runtime complexity of O(n + m) and space complexity of O(n). This method may yield much better performance than Collection.containsAll(Collection) depending on the use-case and type of collection used. Thanks to Adrian Nistor, Mert Guldur.
  • CollectionUtils#permutations(Collection) to generate all permutations of a collection. Thanks to Benoit Corne.
  • ListUtils#select() and ListUtils#selectRejected() methods. Thanks to Adam Dyga.
  • ListUtils#partition() to split a List into consecutive sublists. Thanks to Chris Shayan.
  • CollectionUtils#forAllDo(Iterator, Closure). Thanks to Adrian Cumiskey.
  • ListUtils#defaultIfNull(List, List). Thanks to Ivan Hristov.
  • CollectionUtils#filterInverse(Iterable, Predicate). Thanks to Jean-Noel Rouvignac.
  • CollectionUtils#subtract(Iterable, Iterable, Predicate). Thanks to Chris Shayan.
  • CollectionUtils#collate(...) to merge two sorted Collections using the standard O(n) merge algorithm. Thanks to Julius Davies.
  • CollectionUtils#extractSingleton(Collection). Thanks to Geoffrey De Smet.
  • MapUtils#populateMap(MultiMap, ...) to support also "MultiMap" instances as input. Thanks to John Hunsley.
  • ListUtils#indexOf(List, Predicate). Thanks to Nathan Egge.
  • MapUtils#populateMap(Map, Iterable, Transformer, ...). Thanks to Dave Meikle.
  • Added new method "get(int)" to "CircularFifoQueue". Thanks to Sebb.
  • Added serialVersionUID fields for "CompositeCollection", "CompositeSet", "EmptyMapMutator", "EmptySetMutator". Thanks to sebb.
  • Added support for using custom "Equator" objects in "EqualPredicate". Thanks to Stephen Kestle.
  • Added method "CollatingIterator#getIteratorIndex()". Thanks to Fredrik Kjellberg.
  • Added serialization support for "TreeBidiMap". Thanks to Christian Gruenberg.
  • Added serialization support for "FixedOrderComparator" and "TransformingComparator". Thanks to Chaitanya Mutyala.
  • Added constructor "TransformingComparator(Transformer)". Thanks to Stephen Kestle.
  • Added method "MultiValueMap#iterator()" to return a flattened version of "entrySet().iterator()". Clarified javadoc for "entrySet()" that the returned Entry objects are unflattened, i.e. the Entry object for a given key contains all values mapped to this key. Thanks to Nils Kaiser, Alan Mehlo.
  • Added method "ListOrderedMap#putAll(int, Map)". Thanks to Vasily Ivanov.
  • Added support for resettable iterators in "IteratorIterable". Thanks to Dusan Chromy.

Changed classes / methods

  • Resolved generic parameter inconsistency for various static fields, e.g. BagUtils.EMPTY_BAG, TruePredicate.INSTANCE and many others. All accessible static fields use raw types so that they can be used directly without explicit casting. To avoid compiler warnings about unchecked conversion and/or rawtypes use the corresponding factory methods, e.g. BagUtils.emptyBag().
  • Renamed methods "V MultiKeyMap#remove(Object, Object, ...)" to "V MultiKeyMap#removeMultiKey(Object, Object, ...)" to avoid future conflicts with a default method of the Map interface in Java 8.
  • Renamed "V MultiMap#remove(K, V)" to "boolean MultiMap#removeMapping(K, V)" to avoid future conflicts with a default method of the Map interface in Java 8.
  • Refactored the test framework for Bag implementations to extend from "AbstractCollectionTest" by decorating the concrete Bag instance with a CollectionBag or CollectionSortedBag.
  • "UnmodifiableBoundedCollection" does now also implement the marker interface "Unmodifiable" similar as all other unmodifiable decorators.
  • "UnmodifiableTrie#unmodifiableTrie(Trie)" will not decorate again an already unmodifiable Trie. Also the return type has been changed to "Trie" to be consistent with other Unmodifiable decorators.
  • Moved "Equator" interface to base package for consistency.
  • Accept wildcard input where possible, e.g. in copy-constructors, Unmodifiable* decorators and iterators.
  • Narrow return type of "BidiMap#values()" to Set as the values are required to be unique.
  • Made field "collection" in class "AbstractCollectionDecorator" private and added setter "setCollection(Collection)" with scope protected to set the decorated collection during de-serialization.
  • Replaced "Collection" with "Iterable" for method arguments where applicable.
  • Changed "IteratorChain" to use internally a "Queue" instead of a "List". Iterators are removed from the queue once used and can be garbage collected after being exhausted. Additionally removed the methods "setIterator(Iterator)" and "getIterators()".
  • Removed method "setArray(Object)" in class ArrayIterator and method "setArray(Object[])" in class ObjectArrayIterator and made fields array, startIndex and endIndex final and package private.
  • Changed scope of various fields to private / package private where appropriate.
  • An iterator over a "Flat3Map#entrySet()" will now return independent Map.Entry objects that will not change anymore when the iterator progresses.
  • Several closure and transformer implementations in the functor package will now copy an array as input parameter to their constructor (e.g. ChainedClosure).
  • Change base package to "org.apache.commons.collections4".
  • The constructors for all *Utils classes are now private to prevent instantiation.
  • "CompositeSet" does not inherit from "CompositeCollection" anymore. The inner class "SetMutator" has been updated accordingly. Thanks to Michael Pradel.
  • Change maven coordinates to "org.apache.commons.commons-collections4". Thanks to Olivier Lamy.
  • Move the project structure to a standard maven layout. Thanks to Olivier Lamy.
  • TransformingComparator now supports different types for its input/output values.
  • "CollectionUtils#filter(Iterable, Predicate)" will now return whether the collection has been modified. Thanks to Jean-Noel Rouvignac.
  • "NOPClosure" is now a final class. Thanks to Goran Hacek.
  • Fields transformer and decorated in class "TransformingComparator" are now final. Thanks to sebb.
  • "SetUniqueList#subList()" will now return an unmodifiable list as changes to it may invalidate the parent list. Thanks to Christian Semrau, Thomas Vahrst.
  • Calling "CollectionUtils#sizeIsEmpty(null)" will now return true. Thanks to Benjamin Bentmann.
  • The predicate that rejected an object to be added to a "PredicatedCollection" is now contained in the respective exception message. Thanks to Chris Lewis.
  • "TreeBag" will now only accept "Comparable" objects as input when used with natural ordering. Thanks to David Saff.
  • The static factory methods have been renamed from "getInstance()" to a camel-case version of the class name, e.g. "truePredicate()" for class "TruePredicate". Thanks to Stephen Kestle.
  • "MultiValueMap" is now serializable. Thanks to Wouter de Vaal.
  • Return concrete class in static factory methods instead of base class interface (except for Unmodifiable decorators). Thanks to Torsten Curdt.
  • "CollectionUtils#size(Collection)" now returns 0 when called with null as input. Thanks to Stepan Koltsov,sebb.
  • "CollectionUtils#addAll(...)" methods now return if the collection has been changed by this operation. Thanks to Vasily Ivanov.
  • "CompositeCollection", "CompositeMap" and "CompositeSet" are now serializable. Thanks to Pal Denes.
  • The "CollectionUtils#select(Collection, Predicate, Collection)" method will now return the output collection.
  • "CollectionUtils#forAllDo(Collection, Closure)" now returns the provided closure. Thanks to Jim Cakalic.
  • Make generic versions of all classes in collections.
  • Switch Abstract*Decorator classes to expose decorated() protected method instead of the decorated collection directly. Each class overrides decorated() to add its type covariantly, thus getList()/getSet() etc. methods are removed
  • ArrayStack is now deprecated and will be removed in the next major release. It is replaced by the java.util.Deque interface available from Java 6.

Bugfixes

  • "CollectionBag" will now also respect the contract of the decorated bag in case a null argument is provided to either removeAll or retainAll.
  • Fixed collision detection/resolution when calling "CompositeSet#addComposited(...)" with more than one Set as argument.
  • Fixed conversion of timeout parameters in "PassiveExpiringMap".
  • ListOrderedMap#putAll(index, Object, Object) does not throw an exception anymore if the map contains null values. Additionally added javadoc clarification on the supported bounds for the index parameter. Thanks to Ning Chen.
  • Improved performance of "AbstractMapBag#containsAll(Collection)" by returning immediately after a difference has been found. Thanks to Adrian Nistor.
  • Added additional clarification to javadoc of interface "Put" wrt return type of "put(Object, Object)" method. Thanks to Matt Benson, sebb.
  • Tree traversal with a TreeListIterator will not be affected anymore by the removal of an element directly after a call to previous(). Thanks to Jeffrey Barnes.
  • Adapt and/or ignore several unit tests when run on a IBM J9 VM (specification version 1.6.0) due to a faulty "java.util.TreeMap" implementation.
  • SetUniqueList.set(int, E) now works correctly if the object to be inserted is already placed at the given position. Thanks to Thomas Vahrst, John Vasileff.
  • MultiKeyMap.clone() now correctly calls super.clone(). Thanks to Thomas Vahrst.
  • Improve performance of "TreeList#addAll" and "TreeList(Collection)" by converting the input collection into an AVL tree and efficiently merge it into the existing tree. Thanks to Jeffrey Barnes.
  • Fixed performance issue in "SetUniqueList#retainAll" method for large collections. Thanks to Mert Guldur.
  • Fixed performance issue in "ListOrderedSet#retainAll" method for large collections. Thanks to Adrian Nistor.
  • Improved performance of "ListOrderedMap#remove(Object)" method. Thanks to Adrian Nistor.
  • Update javadoc for "ListUtils#lazyList()" and "ListUtils#fixedSizeList()". Thanks to Benedikt Ritter.
  • Added clarifying javadoc wrt runtime complexity of "AbstractDualBidiMap#retainAll". Thanks to Adrian Nistor.
  • Added clarifying javadoc wrt runtime complexity of "AbstractLinkedList#retainAll". Thanks to Adrian Nistor.
  • Added clarifying javadoc wrt runtime complexity of "AbstractLinkedList#removeAll". Thanks to Adrian Nistor.
  • Fixed several compilation issues with older Java 1.6 compilers.
  • Improved performance of "removeAll()" method for sets returned by "DualHashBidiMap#entrySet()". Thanks to Adrian Nistor.
  • Improved performance of "CollectionUtils#subtract" methods. Thanks to Adrian Nistor.
  • Fixed possible "IndexOutOfBoundsException" in "ListOrderedMap#putAll". Thanks to Adrian Nistor.
  • Improved performance of "SetUniqueList#addAll" method. Thanks to Adrian Nistor.
  • Improved performance of "ListOrderedSet#addAll" method. Thanks to Adrian Nistor.
  • Improved performance of "SetUniqueList#removeAll". Thanks to Adrian Nistor.
  • Improved performance of "ListOrderedSet#remove(Object)" in case the object is not contained in the Set. Thanks to Adrian Nistor.
  • Improved performance of "ListUtils#subtract" method. Thanks to Adrian Nistor.
  • Added missing null check in "CollectionUtils#addIgnoreNull(Collection, Object)". Thanks to Shin Hwei Tan.
  • Fixed javadoc for "MapUtils#toProperties(Map)". Thanks to Shin Hwei Tan.
  • Clarified javadoc for "TransformerUtils#mapTransformer" for null input. Thanks to Shin Hwei Tan.
  • Clarified javadoc for "FactoryUtils#prototypeFactory" for null input. Thanks to Shin Hwei Tan.
  • Fixed inconsistent javadoc for "MapUtils#synchronizedMap(Map)". Thanks to Shin Hwei Tan.
  • Fixed infinite loop when calling "UnmodifiableBoundedCollection#unmodifiableBoundedCollection()". Thanks to Dave Brosius.
  • Fixed javadoc for several methods wrt expected NullPointerExceptions. Thanks to Shin Hwei Tan.
  • "DualTreeBidiMap" now uses the correct comparator for the reverse map during de-serialization.
  • "TransformedMap" in the package "splitmap" can now be serialized.
  • "FilterListIterator#hasNext" does not throw a NullPointerException anymore to comply to the Java iterator specification. Thanks to Sai Zhang.
  • "ListUtils#intersection(List, List)" will now also work correctly if there are duplicate elements in the provided lists. Thanks to Mark Shead.
  • "AbstractCollectionDecorator" will now use internally "decorated()" to access the decorated collection. Thanks to Adam Gent.
  • Removed debug output in "MapUtils#getNumber(Map)". Thanks to Michael Akerman.
  • Fixed javadoc for all "transformedXXX(XXX)" methods in the respective Utils classes to clarify that existing objects in the list are not transformed. Thanks to Paul Benedict.
  • Singleton classes in package "functors" are now correctly de-serialized. Thanks to Goran Hacek.
  • Removed broken methods "equals(Object)" and "hashCode()" in class "NOPClosure". Thanks to Goran Hacek.
  • Simplified exceptions as the cause is available from the parent. Thanks to sebb.
  • Fixed cache assignment for "TreeBidiMap#entrySet". Thanks to sebb.
  • Synchronized access to lock in "StaticBucketMap#size()". Thanks to sebb.
  • Added clarification to javadoc of "ListOrderedMap" that "IdentityMap" and "CaseInsensitiveMap" are not supported. Thanks to Tom Parker.
  • Improve javadoc of "CollatingIterator" wrt the used "Comparator" and throw a NullPointerException in "CollatingIterator#least" if no comparator is set. Thanks to Michael Krkoska.
  • "LRUMap#keySet()#remove(Object)" will not throw a "ConcurrentModificationException" anymore. Thanks to Joerg Schaible.
  • Improved performance of "ListUtils#intersection(List, List)". Thanks to Thomas Rogan, Jilles van Gurp.
  • Changed behavior of "CaseInsensitiveMap" constructor to be compliant with "HashMap" in case the initial capacity is set to zero. Thanks to Maarten Brak.
  • Improved performance of "StaticBucketMap#putAll(Map)" by iterating over the entry set. Thanks to sebb.
  • Avoid redundant null check in "IteratorUtils#getIterator(Object)". Thanks to sebb.
  • Use a private method to populate the object in "AbstractHashedMap(Map)". Thanks to sebb.
  • Fixed javadoc of "LRUMap" wrt to the maxSize parameter of the constructor. Thanks to ori.
  • Use of final keyword where applicable, minor performance improvements by properly initializing the capacity of newly created collections when known in advance. Thanks to Peter Lawrey, Gary Gregory.
  • "SetUniqueList#subList()#contains(Object)" will now correctly check the subList rather than the parent list. Thanks to Christian Semrau.
  • "SetUniqueList#set(int, Object)" will now correctly enforce the uniqueness constraint. Thanks to Rafał Figas,Bjorn Townsend.
  • Improved javadoc for "Unmodifiable*" classes wrt behavior when the users tries to modify the collection. Thanks to Emmanuel Bourg.
  • "CaseInsensitiveMap" will now convert input strings to lower-case in a locale-independant manner. Thanks to Benjamin Bentmann.
  • Fixed javadoc for "ListUtils#transformedList(List)" to clarify that existing objects in the list are not transformed. Thanks to Paul Benedict.
  • "MultiKey" will now be correctly serialized/de-serialized. Thanks to Joerg Schaible.
  • Fixed javadoc for methods "firstKey()" and "lastKey()" in class "AbstractLinkedMap". Thanks to Lisen Mu.
  • "Flat3Map#remove(Object)" will now return the correct value mapped to the removed key if the size of the map is less or equal 3. Thanks to ori.
  • Removed unused variables in "TreeBidiMap". Thanks to Henri Yandell.
  • "SetUniqueList.addAll(int, Collection)" now correctly add the collection at the provided index. Thanks to Joe Kelly.
  • Fixed several unit tests which were using parameters to "assertEquals(...)" in wrong order. Thanks to Mark Hindess.
  • "MultiValueMap#put(Object, Object)" and "MultiValueMap#putAll(Object, Collection)" now correctly return if the map has changed by this operation.
  • "CollectionUtils#removeAll" wrongly called "ListUtils#retainAll". Thanks to Tom Leccese.
  • Calling "setValue(Object)" on any Entry returned by a "Flat3Map" will now correctly set the value for the current entry. Thanks to Matt Bishop.
  • "MultiKey#toString()" will now use "Arrays#toString(List)". Thanks to Hendrik Maryns.

For a full list of changes in this release, refer to the Change report.