Changelog History
-
v7.0.3 Changes
March 16, 2016๐ Bug Fixes
- ๐ Fixed memory leak in HashBiMap.
- ๐ Fixed incorrect code path in key collision handling and keyset iterator based remove operation in primitive Maps with Hashing Strategy.
Acquiring Eclipse Collections
Maven
\<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-api\</artifactId\> \<version\>7.0.3\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections\</artifactId\> \<version\>7.0.3\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-testutils\</artifactId\> \<version\>7.0.3\</version\> \<scope\>test\</scope\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-forkjoin\</artifactId\> \<version\>7.0.3\</version\> \</dependency\>
Gradle
compile 'com.goldmansachs:gs-collections-api:7.0.3'compile 'com.goldmansachs:gs-collections:7.0.3'testCompile 'com.goldmansachs:gs-collections-testutils:7.0.3'compile 'com.goldmansachs:gs-collections-forkjoin:7.0.3'
Ivy
\<dependency org="com.goldmansachs" name="gs-collections-api" rev="7.0.3" /\> \<dependency org="com.goldmansachs" name="gs-collections" rev="7.0.3" /\> \<dependency org="com.goldmansachs" name="gs-collections-testutils" rev="7.0.3" /\> \<dependency org="com.goldmansachs" name="gs-collections-forkjoin" rev="7.0.3"/\>
-
v7.0.2
February 19, 2016 -
v7.0.1 Changes
March 16, 2016๐ Bug Fixes
๐ Fixed UnifiedSet.ChainedBucket.removeLongChain() method to handle many collisions in one bucket.
Acquiring Eclipse Collections
Maven
\<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-api\</artifactId\> \<version\>7.0.1\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections\</artifactId\> \<version\>7.0.1\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-testutils\</artifactId\> \<version\>7.0.1\</version\> \<scope\>test\</scope\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-forkjoin\</artifactId\> \<version\>7.0.1\</version\> \</dependency\>
Gradle
compile 'com.goldmansachs:gs-collections-api:7.0.1'compile 'com.goldmansachs:gs-collections:7.0.1'testCompile 'com.goldmansachs:gs-collections-testutils:7.0.1'compile 'com.goldmansachs:gs-collections-forkjoin:7.0.1'
Ivy
\<dependency org="com.goldmansachs" name="gs-collections-api" rev="7.0.1" /\> \<dependency org="com.goldmansachs" name="gs-collections" rev="7.0.1" /\> \<dependency org="com.goldmansachs" name="gs-collections-testutils" rev="7.0.1" /\> \<dependency org="com.goldmansachs" name="gs-collections-forkjoin" rev="7.0.1"/\>
-
v7.0.0 Changes
November 04, 2015Acquiring GS Collections
Maven
\<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-api\</artifactId\> \<version\>7.0.0\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections\</artifactId\> \<version\>7.0.0\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-testutils\</artifactId\> \<version\>7.0.0\</version\> \<scope\>test\</scope\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-forkjoin\</artifactId\> \<version\>7.0.0\</version\> \</dependency\>
Ivy
\<dependency org="com.goldmansachs" name="gs-collections-api" rev="7.0.0" /\> \<dependency org="com.goldmansachs" name="gs-collections" rev="7.0.0" /\> \<dependency org="com.goldmansachs" name="gs-collections-testutils" rev="7.0.0" /\> \<dependency org="com.goldmansachs" name="gs-collections-forkjoin" rev="7.0.0"/\>
๐ฅ Breaking Changes
- ๐
MutableCollection.removeIf()
now returnsboolean
. - Sorted sets, bags, and maps implement
ReversibleIterable
. AddedOrderedMap
interface to represent a linked hash map. - Overrode
BiMap.partition()
to returnPartitionUnsortedSet
. UnifiedMap
andUnifiedSet
now throw if constructed with a load factor greater than 1.toStringOfItemToCount()
inImmutableEmptyBag
now consistent with other Bags.
Returns"{}"
instead of""
๐ New Functionality
Primitive Collections
๐
<Primitive>List.binarySearch()
Fixes #20ObjectPrimitiveHashMapWithHashingStrategy
Similar to
ObjectPrimitiveHashMap
but uses aHashingStrategy
to hash and compare keys. Analogous toUnifiedMapWithHashingStrategy
.<Primitive>Iterable.each()
๐ Behaves exactly same as
<Primitive>Iterable.forEach()
. Added to be in sync withRichIterable.each(Procedure)
that was introduced in 6.0 to avoid ambiguity conflict withIterable.forEach(Consumer)
.Lazy<Primitive>Iterable.collect<Primitive>()
aggregateInPlaceBy()
,aggregateBy()
,zip()
,zipWithIndex()
,partition()
,selectInstancesOf()
,collectIf()
,groupBy()
, andgroupByEach()
onMutablePrimitiveObjectMap
๐ Use the Kahan summation algorithm on
sum()
andsumBy()
methods on primitive collectionsOther new Functionality
CharAdapter
,CodePointAdapter
andCodePointList
CharAdapter
implementsCharSequence
andImmutableCharList
, and it represents String as a collection of char values.CharPointAdapter
implementsCharSequence
andImmutableIntList
. It behaves similarly toCharAdapter
but it represents String as the unicode codepoint values that are ints.CharPointList
is similar toCharPointAdapter
but it calculates and caches the unicode code point values as an ImmutableIntList internally.CharAdapter chars = CharAdapter.adapt("This is an example");CodePointAdapter codePoints = CodePointAdapter.adapt("Can you read this Kanji \"\uD840\uDC00\"? I cannot.");CodePointList codePointList = CodePointList.from("BMP stands for Basic Multilingual Pane. \"\uD840\uDC00\" is a unicode character outside BMP.");System.out.println("Upper case: " + chars.collectChar(Character::toUpperCase));System.out.println("Unicode character outside Basic Multilingual Pane: " + codePoints.reject(Character::isBmpCodePoint).distinct());System.out.println("English only: " + codePointList.reject(Character::isIdeographic));
๐จ Prints
Upper case: THIS IS AN EXAMPLE Unicode character outside Basic Multilingual Pane: ๐ English only: BMP stands for Basic Multilingual Pane. "" is a unicode character outside BMP.
ImmutableSortedBag
ListIterable.distinct(HashingStrategy)
Returns a new
ListIterable
containing the distinct elements in this list. Conceptually similar tonew UnifiedSetWithHashingStrategy(hashingStrategy, listIterable).toList()
but retains the original order.MutableBagMultimap.putOccurrences(K key, V value, int occurrences)
โ Adds
occurrences
ofvalue
to theMutableBag
atkey
in the multimap.MutableList.shuffleThis(): MutableList
Shuffles this list and returns this list. Overload optionally takes a
Random
.Predicates.cast()
andFunctions.cast()
๐ Allows a Java 8 lambda or method reference to be used in a method taking a predicate or a function without requiring a cast. The methods can be used in places where two or more method overloads could apply when used with a lambda or method reference.
Lists.mutable.of(1, 2, null).removeIf(each -\> each == null);
This code fails to compile with the following error.
Error: java: reference to removeIf is ambiguous both method removeIf(java.util.function.Predicate\<? super E\>) in java.util.Collection and method removeIf(com.gs.collections.api.block.predicate.Predicate\<? super T\>) in com.gs.collections.api.collection.MutableCollection match
โช You can work around the problem by using a cast or the method
Predicates.cast()
.Lists.mutable.of(1, 2, null).removeIf(Predicates.cast(each -\> each == null));
โ Add factory method for creating mutable sets and maps of a given initial capacity.
For example:
Sets.mutable.withInitialCapacity(100)
๐ Optimizations and Performance Tests
- โก๏ธ Optimize
FastList.addAll()
andUnifiedSet.addAll()
forRandomAccess
lists. - โก๏ธ Optimize
UnifiedMap
's short-circuit methods to not delegate to an iterator. - ๐จ Refactor
ImmutableSortedBag.newWith()
andnewWithout()
to take O(n) time. - โ Add JDK 8 Streams based JMH tests for
FastList
. - โ Add JMH Tests for
HashMap<Integer, Integer>
๐ Bug Fixes
- ๐ Fix bug in
CollectIterable.toArray()
where it returnsT[]
instead ofObject[]
. - ๐ Fix iterator's
remove()
method inObjectPrimitiveHashMap
so that it doesn't rehash. - ๐ Fix code point iteration in
StringIterate
and provideCharAdapter
andCodePointList
as OO alternatives for string iteration.
๐ Documentation and Deprecation
- โ Add information about required Java versions to
README.md
. Fixes #18. - โจ Enhance Javadoc of
Iterate
. - โก๏ธ Update Javadoc in
InternalIterable
andRichIterable
to include Java 8 lambda examples. - ๐ Deprecate
ArrayIterate.sort()
and recommend direct calls toArrays.sort()
. - ๐ Deprecate overloaded methods in
StringIterate
and add specialization alternatives that work better with Java 8 lambdas.
- ๐
-
v6.2.0 Changes
June 09, 2015Binaries
Javadoc
Acquiring GS Collections
Maven
\<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-api\</artifactId\> \<version\>6.2.0\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections\</artifactId\> \<version\>6.2.0\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-testutils\</artifactId\> \<version\>6.2.0\</version\> \<scope\>test\</scope\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-forkjoin\</artifactId\> \<version\>6.2.0\</version\> \</dependency\>
Ivy
\<dependency org="com.goldmansachs" name="gs-collections-api" rev="6.2.0" /\> \<dependency org="com.goldmansachs" name="gs-collections" rev="6.2.0" /\> \<dependency org="com.goldmansachs" name="gs-collections-testutils" rev="6.2.0" /\> \<dependency org="com.goldmansachs" name="gs-collections-forkjoin" rev="6.2.0"/\>
Optimizations
- ๐ Improve primitive map performance.
- โก๏ธ Optimize addAll/removeAll on HashBag when a Bag is passed as the parameter.
๐ Bug Fixes
- ๐ Fix bug in remove() in HashBag's iterator.
- ๐ Fix bug in remove() in HashBag and TreeBag's iterators.
-
v6.1.0 Changes
March 25, 2015Binaries
Javadoc
JDiff
Differences between 6.0.0 and 6.1.0
Acquiring GS Collections
Maven
\<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-api\</artifactId\> \<version\>6.1.0\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections\</artifactId\> \<version\>6.1.0\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-testutils\</artifactId\> \<version\>6.1.0\</version\> \<scope\>test\</scope\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-forkjoin\</artifactId\> \<version\>6.1.0\</version\> \</dependency\>
Ivy
\<dependency org="com.goldmansachs" name="gs-collections-api" rev="6.1.0" /\> \<dependency org="com.goldmansachs" name="gs-collections" rev="6.1.0" /\> \<dependency org="com.goldmansachs" name="gs-collections-testutils" rev="6.1.0" /\> \<dependency org="com.goldmansachs" name="gs-collections-forkjoin" rev="6.1.0"/\>
๐ New Functionality
๐ Travis CI build
๐ A continuous build runs at travis-ci and its status is reflected in the README badge.
๐ Allow ArrayList to have subclasses.
๐ Fixes #19.
ParallelIterable.flatCollect()
Optimizations
- โก๏ธ Optimize ArrayList.addAll(PrimitiveIterable) to avoid an array copy when the parameter is also a ArrayList. Fixes #19.
- โก๏ธ Optimize primitive maps/sets probing method.
๐ Bug Fixes
- ๐ Fix size() on the views of ConcurrentHashMap.
- ๐ Fix the iteration order of several iteration patterns.
๐ Performance and memory tests
๐ Many new performance and memory tests supporting the material in the presentation "Scala Collections Performance" at Scala Days San Francisco 2015. There are new JMH tests for several lists, sorted sets, and maps as well as new memory tests for several sets and maps.
-
v6.0.0 Changes
February 09, 2015Binaries
Javadoc
JDiff
Differences between 5.1.0 and 6.0.0
Acquiring GS Collections
Maven
\<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-api\</artifactId\> \<version\>6.0.0\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections\</artifactId\> \<version\>6.0.0\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-testutils\</artifactId\> \<version\>6.0.0\</version\> \<scope\>test\</scope\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-forkjoin\</artifactId\> \<version\>6.0.0\</version\> \</dependency\>
Ivy
\<dependency org="com.goldmansachs" name="gs-collections-api" rev="6.0.0" /\> \<dependency org="com.goldmansachs" name="gs-collections" rev="6.0.0" /\> \<dependency org="com.goldmansachs" name="gs-collections-testutils" rev="6.0.0" /\> \<dependency org="com.goldmansachs" name="gs-collections-forkjoin" rev="6.0.0"/\>
๐ New Functionality
RichIterable API
RichIterable.each(Procedure)
Java 8 introduced
Iterable.forEach(Consumer)
which can cause problems for users ofRichIterable.forEach(Procedure)
.Consumer
andProcedure
have the same shape, so passing in a lambda is ambiguous.FastList.newListWith(1, 2, 3).forEach(System.out::println);
This code fails with the following compiler error.
Error: reference to forEach is ambiguous both method forEach(java.util.function.Consumer\<? super T\>) in java.lang.Iterable and method forEach(com.gs.collections.api.block.procedure.Procedure\<? super T\>) in com.gs.collections.impl.list.mutable.FastList match
โช You can work around this problem by using a cast,
Procedures.cast()
, or by usingRichIterable.each(Procedure)
which behaves exactly likeInternalIterable.forEach(Procedure)
.FastList.newListWith(1, 2, 3).forEach((Procedure\<? super Integer\>) System.out::println);FastList.newListWith(1, 2, 3).forEach(Procedures.cast(System.out::println));FastList.newListWith(1, 2, 3).each(System.out::println);
RichIterable.tap(Procedure): RichIterable
Executes the
Procedure
for each element in the iterable and returns theRichIterable
. Similar toRichIterable.forEach(Procedure)
andRichIterable.each(Procedure)
but returnsthis
.LazyIterable.tap(Procedure): LazyIterable
LazyIterable.tap(Procedure)
overridesRichIterable.tap(Procedure)
and executes lazily. It is useful to "tap into" a method chain, executing aProcedure
on every element of theLazyIterable
without ending the chain or forcing evaluation.RichIterable\<String\> list = Lists.mutable.of("One", "Two", "Three", "Four"); list.asLazy() .tap(each -\> System.out.println(each + " --(Each element prints this)")) .select(StringPredicates.contains("o")) .tap(selected -\> System.out.println(selected + " --(Only selected element prints this)")) .collect(String::toUpperCase) .tap(collected -\> System.out.println(collected + " --(Collected element prints this)")) .each(a -\> {}); // force evaluation
๐จ Prints
One --(Each element prints this)Two --(Each element prints this)Two --(Only selected element prints this)TWO --(Collected element prints this)Three --(Each element prints this)Four --(Each element prints this)Four --(Only selected element prints this)FOUR --(Collected element prints this)
RichIterable.toSortedBag(), RichIterable.toSortedBag(Comparator), and RichIterable toSortedBagBy(Function)
RichIterable.toSortedBag()
converts the collection to aMutableSortedBag
implementation and sorts it using the natural order of the elements.RichIterable.toSortedBag(Comparator)
sorts using theComparator
parameter.RichIterable.toSortedBagBy(Function)
sorts based on the natural order of the attribute returned by theFunction
parameter.RichIterable.groupByUniqueKey(Function): MapIterable.
๐ป Similar to
RichIterable.groupBy(Function)
. The keys returned by theFunction
must be unique, otherwise an exception is thrown. Since the keys are unique,groupByUniqueKey()
returns aMapIterable
instead of aMultimap
.RichIterable.sumBy(Int|Long|Float|Double)
RichIterable.sumByInt(Function<T, V> groupBy, IntFunction<? super T> function): ObjectLongMap<V>
RichIterable.sumByLong(Function<T, V> groupBy, LongFunction<? super T> function): ObjectLongMap<V>
RichIterable.sumByFloat(Function<T, V> groupBy, FloatFunction<? super T> function): ObjectDoubleMap<V>
RichIterable.sumByDouble(Function<T, V> groupBy, DoubleFunction<? super T> function): ObjectDoubleMap<V>
Groups the elements in the
RichIterable
by the groupByFunction
. Each group is converted to numbers using the primitive function and then summed.sumByInt()
andsumByLong()
returnObjectLongMap
.sumByFloat()
andsumByDouble()
returnObjectDoubleMap
.OrderedIterable API
OrderedIterable interface for order dependent functionality.
An
OrderedIterable
is aRichIterable
with some meaningful order, such as insertion order, access order, or sorted order.ReversibleIterable
andSortedIterable
now extendOrderedIterable
.Several methods were pulled up to
OrderedIterable
.indexOf(Object)
takeWhile(Predicate)
,dropWhile(Predicate)
, andpartitionWhile(Predicate)
distinct()
toStack()
๐ Other methods on
InternalIterable
andRichIterable
are now deprecated because they imply a meaningful order which not all containers have. These methods are overridden onOrderedIterable
so that the deprecation warning will not appear on ordered collections.getFirst()
andgetLast()
forEach(startIndex, endIndex, procedure)
forEachWithIndex(ObjectIntProcedure)
forEachWithIndex(fromIndex, toIndex, objectIntProcedure)
OrderedIterable.corresponds(OrderedIterable, Predicate2).
Returns true if both
OrderedIterable
s have the same length and the predicate returnstrue
for all elements e1 of the currentOrderedIterable
and e2 of the otherOrderedIterable
.The predicate is evaluated for pairs of elements at the same position in both
OrderedIterable
s. Thecorresponds()
method short circuits as soon as it finds a pair of elements which do not correspond.MutableList\<Integer\> integers1 = FastList.newListWith(1, 2, 2, 3, 3, 3, 4, 4, 4, 4);MutableList\<Integer\> integers2 = FastList.newListWith(2, 3, 3, 4, 4, 4, 5, 5, 5, 5);Assert.assertTrue(integers1.corresponds(integers3, Predicates2.lessThan()));
OrderedIterable.detectIndex(Predicate).
Returns the index of the first element which satisfies the
Predicate
or-1
if no elements do. ThedetectIndex()
method short circuits as soon as it finds an element which satisfies thePredicate
.ListIterable\<Integer\> list = FastList.newListWith(1, 1, 2, 2, 3, 3);Assert.assertEquals(2, list.detectIndex(integer -\> integer == 2));Assert.assertEquals(-1, list.detectIndex(integer -\> integer == 4));
ReversibleIterable API
ReversibleIterable.detectLastIndex(Predicate).
Returns the index of the last element which satisfies the
Predicate
or-1
if no elements do. ThedetectLastIndex()
method iterates in reverse order and short circuits as soon as it finds an element which satisfies thePredicate
.ListIterable\<Integer\> list = FastList.newListWith(1, 1, 2, 2, 3, 3);Assert.assertEquals(3, list.detectLastIndex(integer -\> integer == 2));Assert.assertEquals(-1, list.detectLastIndex(integer -\> integer == 4));
ReversibleIterable.distinct().
Same as
ReversibleIterable.distinct()
for primitive collections.ReversibleIterable.take(int n) and ReversibleIterable.drop(int n).
take()
Returns the first
n
elements of the iterable or all the elements in the iterable ifn
is greater than the length of the iterable.MutableList\<Integer\> list = FastList.newListWith(1, 2, 3, 4, 5);Assert.assertEquals(FastList.newList(), list.take(0));Assert.assertEquals(FastList.newListWith(1, 2, 3), list.take(3));Assert.assertEquals(FastList.newListWith(1, 2, 3, 4, 5), list.take(6));
โฌ๏ธ drop()
Returns an iterable after skipping the first
n
elements or an empty iterable ifn
is greater than the length of the iterable.MutableList\<Integer\> list = FastList.newListWith(1, 2, 3, 4, 5);Assert.assertEquals(FastList.newListWith(1, 2, 3, 4, 5), list.drop(0));Assert.assertEquals(FastList.newListWith(4, 5), list.drop(3));Assert.assertEquals(FastList.newListWith(), list.drop(6));
ParallelIterable API
ListIterable.asParallel(), SetIterable.asParallel(), and SortedSetIterable.asParallel().
In 5.0,
asParallel()
was added toFastList
andUnifiedSet
. Now it's on the interfaces ListIterable, SetIterable and SortedSetIterable as well.ListIterable\<Person\> people = ...;ExecutorService threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());int batchSize = 10\_000;ParallelListIterable\<Person\> peopleParallel = people.asParallel(threadPool, batchSize);
min(), max(), minBy(), and maxBy() on ParallelIterable.
Similar to the same methods on
RichIterable
. These methods force evaluation.ParallelListIterable\<Person\> peopleParallel = people.asParallel(threadPool, batchSize);Integer youngestAge = peopleParallel.collect(Person::getAge).min();Integer oldestAge = peopleParallel.collect(Person::getAge).max();Person youngestPerson = peopleParallel.minBy(Person::getAge);Person oldestPerson = peopleParallel.maxBy(Person::getAge);
sumOfInt(), sumOfFloat(), sumOfLong(), sumOfDouble() on ParallelIterable.
Similar to the same methods on
RichIterable
. These methods force evaluation.ParallelListIterable\<Person\> peopleParallel = people.asParallel(threadPool, batchSize);long sum1 = peopleParallel.sumOfInt(Person::getIntAttribute);long sum2 = peopleParallel.sumOfLong(Person::getLongAttribute);double sum3 = peopleParallel.sumOfFloat(Person::getFloatAttribute);double sum4 = peopleParallel.sumOfDouble(Person::getDoubleAttribute);
Multimap API
Constructors for Multimaps that take Iterable<Pair<K, V>>.
ListIterable\<Pair\<Integer, String\>\> pairs = ...;Multimap\<Integer, String\> actual = FastListMultimap.newMultimap(pairs);
MutableMultimap.add(Pair).
Similar to
MutableMultimap.put(K, V)
but takesPair<K, V>
instead.Multimap.forEachKeyMultiValues(Procedure2<K, ? super Iterable>)
Similar to
forEachKeyValue(Procedure2<K, V>)
but theProcedure2
gets invoked on each group of values instead of each individual value.Multimap.selectKeysValues(Predicate2<? super K, ? super V>) and Multimap.rejectKeysValues(Predicate2<? super K, ? super V>).
๐ Similar to
RichIterable.select()
andRichIterable.reject()
but thePredicate2
is evaluated against each key/value pair. The implementation of thePredicate2
is free to ignore either the key or the value.Multimap.selectKeysMultiValues(Predicate2<? super K, ? super Iterable>) and Multimap.rejectKeysMultiValues(Predicate2<? super K, ? super Iterable>).
Similar to
Multimap.selectKeysValues()
andMultimap.rejectKeysValues()
but thePredicate2
takes (K, Iterable) pairs instead of (K, V) pairs.Multimap.collectKeysValues(Function2<? super K, ? super V, Pair<K2, V2>>).
Similar to
RichIterable.collect()
but theFunction2
is applied to each key/value pair.Multimap.collectValues(Function<? super V, ? extends V2>)
Similar to
Multimap.collectKeysValues()
but only transforms keys. It is more efficient than usingMultimap.collectKeysValues()
and passing through the keys unchanged.Multimap<K, V>.flip(): Multimap<V, K>.
Returns a new
Multimap
where the positions of the keys and values are swapped.Other new API
Unify the map interface hierarchy through new interfaces MutableMapIterable and ImmutableMapIterable.
MutableMap
,MutableSortedMap
, andMutableBiMap
now extend a common interfaceMutableMapIterable
.ImmutableMap
,ImmutableSortedMap
, andImmutableBiMap
now extend a common interfaceImmutableMapIterable
. TheSetIterable
andBag
hierarchy had similar changes.๐ MutableIterator.remove()
๐
Mutable<Primitive>Iterator
is a new subclass of<Primitive>Iterator
that adds theremove()
method. It behaves similarly toIterator.remove()
, but does not appear on immutable primitive containers and thus doesn't throwUnsupportedOperationException
. Immutable containers continue to return the read-only<Primitive>Iterator
.Bag.topOccurrences() and Bag.bottomOccurrences().
Bag.topOccurrences()
returns the most frequently occurring item.Bag.bottomOccurrences()
returns the least frequently occurring item. In the event of a tie, all tied items are returned.ImmutableList.subList(fromIndex, toIndex): ImmutableList.
Similar to
List.subList()
but returns anImmutableList
.Primitive forms of MutableList.sortThisBy().
Similar to
sortThisBy(Function)
but taking primitive functions. For example,MutableList\<T\> sortThisByInt(IntFunction\<? super T\> function);MutableList\<T\> sortThisByFloat(FloatFunction\<? super T\> function);...
Pair.swap().
Returns a new
Pair
with the two elements transposed.Functions.swappedPair().
Returns a
Function
which swaps the two elements in aPair
. Similar to Pair::swap but doesn't rely on Java 8.StringIterate.chunk(int).
๐ Breaks up a String into fixed size chunks. Similar to
RichIterable.chunk()
, but forStrings
rather than collections.๐ New Containers
ImmutableBiMap
ImmutableBiMap
s can be created by using theBiMaps
factory or by callingMutableBiMap.toImmutable()
.MutableBiMap\<Integer, Character\> biMap = ...;ImmutableBiMap\<Integer, Character\> characters = biMap.toImmutable();
MultiReaderFastListMultimap, MultiReaderUnifiedSetMultimap, and MultiReaderHashBagMultimap.
Thread-safe
Multimaps
backed byConcurrentMutableMap
s of multi-reader collections.โ Tests
โ JUnit Runner for interfaces containing concrete tests. New test suite leveraging virtual extension methods.
โ A new JUnit
Runner
namedJava8Runner
that extends the standard test runner by looking for tests in interfaces in addition to classes. Tests in interfaces are default methods annotated with@Test
. For example:@Testdefault void MutableList\_sortThis() { MutableList\<Integer\> mutableList = this.newWith(5, 1, 4, 2, 3); MutableList\<Integer\> sortedList = mutableList.sortThis(); assertSame(mutableList, sortedList); assertEquals(Lists.immutable.with(1, 2, 3, 4, 5), sortedList); }
โ This allows for a form of multiple inheritance in tests. For example, a
MutableList
is both aMutableCollection
and aListIterable
. Any assertions aboutMutableCollection
s andListIterable
s should be true forMutableList
s as well. Thus, the test interfaceMutableListTestCase
extends bothMutableCollectionTestCase
andListIterableTestCase
.โ
unit-tests-java8
is a new test suite containing over 50 new test classes and 60 new test interfaces.โ Additional JMH Tests
๐ Performance tests covering
min
,max
,minBy
,maxBy
,sumOf
, andsumBy
.Optimizations
โก๏ธ Optimize primitive hash maps with keys and values of the same primitive type.
Primitive hash maps with keys and values of the same primitive type (
IntIntHashMap
,DoubleDoubleHashMap
, etc.), keys and values are now stored in a single array of double the length.๐ This yields a small memory savings and a speed increase in larger maps. The corresponding JMH performance tests are
IntIntMapTest
andLongIntMapTest
.โก๏ธ Optimize code paths that unnecessarily use iterator by delegating to IterableIterate by delegating to forEach() instead.
๐ Bug Fixes
- โ Make ArrayListAdapterSerializationTest more robust for future versions of Java. Fixes #12.
- ๐ Fix array index bug in ArrayList.sortThis(). Fixes #16.
- ๐ Fix ObjectHashMap.injectInto() to include sentinels values.
- ๐ Fix ImmutableSortedMap.entrySet() to return entries sorted by key.
- ๐ Fix CountSetTest to delegate to CountSetScalaTest. Fixes #15.
- ๐ Fix concurrency issue in the aggregateBy tests.
- ๐ Fix the iteration order of several iteration patterns.
- ๐ Use the Kahan summation algorithm to handle double and float precision in sumOf().
- ๐ Fix looping logic in SortedSetIterable.forEach() and SortedSetIterable.forEachWithIndex() with fromIndex and toIndex.
- ๐ Fix CompositeFastList.size() to execute in constant time.
- ๐ Fix ListAdapter.reverseThis() to run in linear time.
- ๐ Fix ListIterate.toArray(list, target, startIndex, sourceSize) and ListIterate.getLast() to run in linear time.
- ๐ Fix UnifiedSet.getLast() and UnifiedSetWithHashingStrategy.getLast() to return the last instead of the first element.
-
v5.1.0 Changes
June 02, 2014Binaries
Javadoc
JDiff
Differences between 5.0.0 and 5.1.0
Acquiring GS Collections
Maven
\<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-api\</artifactId\> \<version\>5.1.0\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections\</artifactId\> \<version\>5.1.0\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-testutils\</artifactId\> \<version\>5.1.0\</version\> \<scope\>test\</scope\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-forkjoin\</artifactId\> \<version\>5.1.0\</version\> \</dependency\>
Ivy
\<dependency org="com.goldmansachs" name="gs-collections-api" rev="5.1.0" /\> \<dependency org="com.goldmansachs" name="gs-collections" rev="5.1.0" /\> \<dependency org="com.goldmansachs" name="gs-collections-testutils" rev="5.1.0" /\> \<dependency org="com.goldmansachs" name="gs-collections-forkjoin" rev="5.1.0"/\>
๐ Improvements
๐ Java Microbenchmark Harness performance test suite
๐ There are two new modules named
jmh-scala-tests
andjmh-tests
which include new performance tests leveraging Java Microbenchmark Harness. They supplement the existingperformance-tests
module. The focus of these tests is to compare the performance of various iteration patterns across several libraries, including GS Collections, Java 8 Streams, Scala collections, and Guava. Each iteration pattern is tested in serial and in parallel. Where the API is available, they are also tested eagerly and lazily.โ As an example, here is the test of the GS Collections implementation of
count()
, using serial eager evaluation.@GenerateMicroBenchmarkpublic void serial\_eager\_gsc() { int evens = this.integersGSC.count(each -\> each % 2 == 0); Assert.assertEquals(SIZE / 2, evens); }
โ Use of lambdas in the test suites
โ The GS Collections library is compiled with Java 5 to ensure its backwards compatibility. However, the test modules are free to use any version of Java. Most of the test modules now use Java 8. We've replaced all of the anonymous inner classes with lambdas or method references. We've also replaced many usages of code block factories with the equivalent lambda or method reference. For example, instead of using
Functions.getToString()
, we useString::valueOf
in most tests. -
v5.0.0 Changes
March 21, 2014Binaries
Javadoc
JDiff
API differences between 4.0.0 and 5.0.0
Acquiring GS Collections
Maven
\<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-api\</artifactId\> \<version\>5.0.0\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections\</artifactId\> \<version\>5.0.0\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-testutils\</artifactId\> \<version\>5.0.0\</version\> \<scope\>test\</scope\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-forkjoin\</artifactId\> \<version\>5.0.0\</version\> \</dependency\>
Ivy
\<dependency org="com.goldmansachs" name="gs-collections-api" rev="5.0.0" /\> \<dependency org="com.goldmansachs" name="gs-collections" rev="5.0.0" /\> \<dependency org="com.goldmansachs" name="gs-collections-testutils" rev="5.0.0" /\> \<dependency org="com.goldmansachs" name="gs-collections-forkjoin" rev="5.0.0"/\>
๐ New Functionality
Parallel-Lazy Iteration
๐ Previous versions of GS Collections included parallel evaluation and lazy evaluation as separate features. Parallel-eager utility has been available through the
ParallelIterate
utility class. Serial-lazy evaluation has been available throughLazyIterable
, the view returned byRichIterable.asLazy()
. GS Collections 5.0 adds parallel-lazy evaluation throughParallelIterable
, the view returned byasParallel(ExecutorService, int batchSize)
. The methodasParallel
is not on interfaces likeRichIterable
yet, but rather on a few supported collections, includingFastList
andUnifiedSet
.FastList\<Integer\> integers = FastList.newListWith(1, 2, 3, 4, 5, 6, 7, 8, 9);ExecutorService threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());int batchSize = 2;ParallelListIterable\<Integer\> parallelListIterable = integers.asParallel(threadPool, batchSize);ParallelListIterable\<Integer\> evenNumbers = parallelListIterable.select(each -\> each % 2 == 0); // deferred evaluationParallelListIterable\<String\> evenStrings = evenNumbers.collect(Object::toString); // deferred evaluationMutableList\<String\> strings = evenStrings.toList(); // forced evaluationthreadPool.shutdown();Assert.assertEquals(FastList.newListWith("2", "4", "6", "8"), strings);
The calls to
select
andcollect
are lazy, indicated by the fact that they return subclasses ofParallelIterable
. The call totoList()
forces evaluation.๐ The two parameters to
asParallel
are used to configure parallelism. The code example above sets up a thread pool with one thread per core, which is appropriate for CPU bound tasks. It's possible to configure the thread pool for IO bound tasks, and to share thread pools between multiple calls toasParallel.
The batch size determines the number of elements from the backing collection that get processed by each task submitted to the thread pool. The appropriate batch size for CPU-bound tasks will be much larger, usually 10,000 to 100,000. The right batch size should be determined through thorough performance testing.๐ NOTE: The new parallel-lazy API is experimental and is tagged as
@Beta
. Until we remove the@Beta
annotation, we reserve the right to make incompatible changes to the parallel-lazy API even in minor versions of GS Collections.API
anySatisfyWith
,allSatisfyWith
,noneSatisfyWith
,countWith
,partitionWith
,detectWith
, anddetectWithIfNone
onRichIterable
These are the two-argument forms of
anySatisfy
,allSatisfy
,noneSatisfy
,count
,partition
,detect
anddetectIfNone
. They take aPredicate2
instead of aPredicate
, and a second argument, which is passed as the second argument to thePredicate2
. The two argument forms allow reusing some code blocks that would otherwise have one differing parameter, resulting in less garbage creation. Some of these methods already existed onMutableCollection
and were pulled up toRichIterable
. Here is a comparison betweenanySatisfy
andanySatisfyWith
.Assert.assertTrue(this.newWith(1, 2, 3).anySatisfyWith(Predicates2.equal(), 2));Assert.assertTrue(this.newWith(1, 2, 3).anySatisfy(Predicates.equal(2)));
RichIterable.collect<Primitive>(<Primitive>Function, Mutable<Primitive>Collection target)
The new overload
RichIterable.collect<Primitive>(<Primitive>Function, Mutable<Primitive>Collection target)
is similar tocollect<Primitive>(<Primitive>Function)
, except that the results are gathered into the specified target collection.ListIterable.toImmutable()
,SortedSetIterable.toImmutable()
,UnsortedSetIterable.toImmutable()
,SortedMapIterable.toImmutable()
,UnsortedMapIterable.toImmutable()
,StackIterable.toImmutable()
Previously,
toImmutable()
only existed onMutableCollection
s. It's now available on the read-only interfaces as well. When called on an immutable collection, it returns the same instance.MutableStack\<Integer\> mutableStack = Stacks.mutable.with(1, 2, 3);Verify.assertInstanceOf(ImmutableStack.class, mutableStack.toImmutable());Assert.assertNotSame(mutableStack, mutableStack.toImmutable());StackIterable\<Integer\> immutableStack = Stacks.immutable.with(1, 2, 3);Assert.assertSame(immutableStack, immutableStack.toImmutable());
ListIterable.binarySearch(T)
andListIterable.binarySearch(T, Comparator)
Similar to
java.util.Collections.binarySearch
, but available from the object-oriented API.LazyIterable.distinct()
andLazyIterate.distinct(Iterable)
Similar to
toSet(),
but returns aLazyIterable
(does not force evaluation).MapIterable.flip()
Returns a new associative array where the position of the keys and values have been flipped. Since the values in the
MapIterable
are not necessarily unique,flip()
returns aMultimap
instead of aMapIterable
. Since the keys in theMapIterable
are unique,flip()
returns aSetMultimap
instead of the more generalMultimap
interface. In summary,MapIterable<K, V>.flip()
returnsSetMultimap<V, K>
.MutableSetMultimap\<String, String\> expected = UnifiedSetMultimap.newMultimap(); expected.put("odd", "One"); expected.put("even", "Two"); expected.put("odd", "Three"); expected.put("even", "Four");Assert.assertEquals(expected, UnifiedMap.newWithKeysValues("One", "odd", "Two", "even", "Three", "odd", "Four", "even").flip());
MapIterable.flipUniqueValues()
Similar to
MapIterable.flip()
but asserts that the values in theMapIterable
are unique and thus returnsMapIterable
instead ofMultimap
. ThrowsIllegalArgumentException
if theMapIterable
contains duplicate values.MapIterable\<Integer, String\> map = this.newMapWithKeysValues(1, "1", 2, "2", 3, "3");MapIterable\<String, Integer\> flip = map.flipUniqueValues();Assert.assertEquals(UnifiedMap.newWithKeysValues("1", 1, "2", 2, "3", 3), flip);
MutableMap.getIfAbsentPut(K key, V value)
Gets and returns the value in the map at the specified key. If the map does not contain the key,
getIfAbsentPut()
puts the value in the map and returns it. Similar togetIfAbsentPut(K key, Function0<? extends V> function)
, but takes in a value directly instead of a value factory (Function0
).MutableMap\<Integer, String\> map = UnifiedMap.newWithKeysValues(1, "1", 2, "2", 3, "3");Assert.assertEquals("4", map.getIfAbsentPut(4, "4")); // mutatesAssert.assertEquals("3", map.getIfAbsentPut(3, "5")); // does not mutateVerify.assertContainsKeyValue(3, "3", map);Verify.assertContainsKeyValue(4, "4", map);
MutableMap.add(Pair<K, V>)
โ Adds the key-value pair to the map. It's a convenience method for working with
Pair
s, similar toput(K, V)
.MutableMap\<String, Integer\> map = this.newMapWithKeyValue("A", 1);Assert.assertEquals(Integer.valueOf(1), map.add(Tuples.pair("A", 3)));Assert.assertNull(map.add(Tuples.pair("B", 2)));Verify.assertMapsEqual(UnifiedMap.newWithKeysValues("A", 3, "B", 2), map);
MutableBag.setOccurrences(T item, int occurrences)
Mutates the bag to contain the given number of occurrences of the item. Returns
true
if the bag has been modified as a result of the call tosetOccurrences()
.MutableBag\<String\> bag = HashBag.newBag();MutableBag\<String\> expected = this.newWith("betamax-tape", "betamax-tape");Assert.assertTrue(bag.setOccurrences("betamax-tape", 2));Assert.assertEquals(expected, bag);
ListIterate.reverseForEachWithIndex(List, ObjectIntProcedure)
Iterates over the list in reverse order executing the
ObjectIntProcedure
for each element. The index passed into theObjectIntProcedure
is the actual index of the range.Primitive API
Mutable<Primitive>Collection.retainAll
Like
Collection.retainAll
, but for primitive collections. There are two variants, one that takes a<Primitive>Iterable
, and another that takes varargs.Assert.assertTrue(collection.retainAll(IntArrayList.newListWith(1, 2, 5)));Assert.assertEquals(this.newMutableCollectionWith(1, 2), collection);MutableIntCollection collection = this.newMutableCollectionWith(1, 2, 3);Assert.assertFalse(collection.retainAll(1, 2, 3));Assert.assertEquals(this.newMutableCollectionWith(1, 2, 3), collection);
keysView()
andkeyValuesView()
on primitive mapsReturns a lazy view of keys or key/value pairs respectively.
๐
keySet()
andvalues()
on synchronized, unmodifiable, and immutable primitive maps๐ These methods already existed on the API but threw
UnsupportedOperationException
s in places. They are fully supported now.addToValue(key, amount)
on mutable primitive mapsโ Adds the given amount to the value at the given key and returns the updated value. This method exists only for maps where the values are numeric types (not
boolean
orObject
).MutableByteIntMap map = new ByteIntHashMap();Assert.assertEquals(1, map.addToValue((byte) 0, 1));Assert.assertEquals(ByteIntHashMap.newWithKeysValues((byte) 0, 1), map);Assert.assertEquals(11, map.addToValue((byte) 0, 10));Assert.assertEquals(ByteIntHashMap.newWithKeysValues((byte) 0, 11), map);
Mutable<Primitive>ObjectMap.putAll(<Primitive>ObjectMap)
putAll()
was already implemented onMutableObject<Primitive>Map
and<Primitive><Primitive>Map
. This rounds out the API.Reversible<Primitive>Iterable.asReversed()
Returns a reversed view of the primitive iterable. Like
ReversibleIterable.asReversed()
, but for the primitive API.Reversible<Primitive>Iterable.toReversed()
Returns a reversed copy of the primitive iterable. Like
asReversed()
but executes eagerly.<Primitive>Iterable.injectInto
injectInto
was already implemented on primitive collections and has now been pulled up to the<Primitive>Iterable
interfaces.IntIterable arrayList = IntArrayList.newListWith(1, 2, 3);MutableInteger sum = arrayList.injectInto(new MutableInteger(0), new ObjectIntToObjectFunction\<MutableInteger, MutableInteger\>() { public MutableInteger valueOf(MutableInteger object, int value) { return object.add(value); } });Assert.assertEquals(new MutableInteger(6), sum);
Code Block Factory Methods
Functions.nullSafe(Function)
Returns a null-safe wrapper around the given
Function
. The wrapper delegates to thevalueOf()
method of the delegateFunction
only if the parameter is notnull
, otherwise it returnsnull
or the providednull
replacement value.MutableList\<Integer\> squares = FastList.newListWith(1, 2, null, 3).collect(Functions.nullSafe(Functions.squaredInteger()));Assert.assertEquals(FastList.newListWith(1, 4, null, 9), squares);MutableList\<Integer\> squaresWithNullValue =FastList.newListWith(1, 2, null, 3).collect(Functions.nullSafe(Functions.squaredInteger(), 0));Assert.assertEquals(FastList.newListWith(1, 4, 0, 9), squaresWithNullValue);
Functions2.integerAddition()
Creates a
Function2
that takes in twoInteger
s as parameters and returns their sum.HashingStrategies.chain(HashingStrategy...)
Takes a vararg number of hashing strategies and returns a wrapper
HashingStrategy
that considers objects as equal if all the delegate strategies consider them equal. The hashcode is computed using a strategy similar to code-generatedhashCode()
methods. It start with the first delegate strategy's computed hashcode, and then repeatedly multiplies the accumulated hashcode by31
and adds the next computed hashcode for each remaining delegate strategy.HashingStrategies.identityStrategy()
Returns a
HashingStrategy
that considers objects as equal only if they are the same object. It uses reference equality in the implementation ofequals
, andSystem.identityHashCode
in the implementation ofcomputeHashCode
.HashingStrategies.fromFunctions(Function, Function)
andHashingStrategies.fromFunctions(Function, Function, Function)
Creates a
HashingStrategy
from eachFunction
, chains them, and returns the chain.HashingStrategies.from<Primitive>Function
โก๏ธ Similar to
HashingStrategies.fromFunction(Function)
but optimized for primitives. Implemented in a way that calls toequals
andcomputeHashCode
do not create any garbage.ReversibleIterable
andSortedIterable
InterfacesTwo new interfaces have been introduced in the GS Collections Hierarchy.
ReversibleIterable
is an ordered iterable which can be traversed efficiently forwards or backwards.ReversibleIterable
has extra API for iterating from the end likeasReversed()
andreverseForEach()
. Lists are the most commonReversibleIterable
s, andListIterable
extendsReversibleIterable
.SortedIterable
, is an ordered iterable where the elements are stored in sorted order. Its methodcomparator()
returns theComparator
used to sort the elements, ornull
if they are sorted in natural order.SortedSetIterable
andSortedBag
extendSortedIterable
.๐ Changes in the
Bag
Interface HierarchyThe inheritance hierarchy of
Bag
s is now more consistent withSet
s. We introduced a new interfaceUnsortedBag
, as a sibling ofSortedBag
.Bag
no longer overridescollect
, so it returnsRichIterable
instead ofBag
.SortedBag.collect
returnsListIterable
instead ofBag
.UnsortedBag.collect
returnsUnsortedBag
, which means the implementations ofUnsortedBag.collect
are unchanged. The new interface structure is as follows:The change to the interface hierarchy changed the serialized forms of
TreeBag
andUnmodifiableSortedBag
.๐ Changes to serialized forms
๐ Serialized form of synchronized and unmodifiable collections
๐ The hierarchy of synchronized and unmodifiable collections has been changed slightly.
AbstractSynchronizedMutableCollection
has been extracted fromSynchronizedMutableCollection
, and all the classes that used to extendSynchronizedMutableCollection
likeSynchronizedMutableList
andSynchronizedMutableSet
now extendAbstractSynchronizedMutableCollection
directly. Similar changes have been made to the unmodifiable collections.Serialized form of immutable collections
The serialized forms of
ImmutableSet
,ImmutableBag
andImmutableMap
implementations have been changed.The
ImmutableSet
implementations now use a proxy class for serialization.๐ฆ The implementations of
ImmutableMap
andImmutableBag
already used proxy classes for serialization. These proxy classes were inner classes insideAbstractImmutableMap
andAbstractImmutableBag
respectively. These proxy classes were moved to top level, package private classes. -
v4.2.0 Changes
October 28, 2013Acquiring GS Collections
Maven
\<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-api\</artifactId\> \<version\>4.2.0\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections\</artifactId\> \<version\>4.2.0\</version\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-testutils\</artifactId\> \<version\>4.2.0\</version\> \<scope\>test\</scope\> \</dependency\> \<dependency\> \<groupId\>com.goldmansachs\</groupId\> \<artifactId\>gs-collections-forkjoin\</artifactId\> \<version\>4.2.0\</version\> \</dependency\>
Ivy
\<dependency org="com.goldmansachs" name="gs-collections-api" rev="4.2.0" /\> \<dependency org="com.goldmansachs" name="gs-collections" rev="4.2.0" /\> \<dependency org="com.goldmansachs" name="gs-collections-testutils" rev="4.2.0" /\> \<dependency org="com.goldmansachs" name="gs-collections-forkjoin" rev="4.2.0"/\>
๐ New Functionality
SortedBag
SortedBag
has all of the same properties as aBag
, and additionally maintains order by aComparator
or by the elements' natural order.The main implementation is
TreeBag
which delegates to aTreeSortedMap
to store its data.MutableSortedBag\<Integer\> emptySortedBag = TreeBag.newBag();MutableSortedBag\<Integer\> emptySortedBagWithComparator =TreeBag.newBag(Collections.reverseOrder());MutableSortedBag\<Integer\> naturalOrder =TreeBag.newBagWith(1, 2, 3);MutableSortedBag\<Integer\> reversedOrder =TreeBag.newBagWith(Collections.reverseOrder(), 4, 3, 3, 2, 2, 1);MutableSortedBag\<Integer\> sortedBagFromFastList =TreeBag.newBag(FastList.newListWith(1, 2, 3));MutableSortedBag\<Integer\> sortedBagFromFastListWithComparator =TreeBag.newBag(Collections.reverseOrder(), FastList.newListWith(1, 2, 3));
BiMap
BiMap
is a map that allows users to perform lookups from both directions. Both the keys and the values in a BiMap are unique.The main implementation is
HashBiMap
.inverse()
BiMap.inverse()
returns a view where the position of the key type and value type are swapped.MutableBiMap\<Integer, String\> biMap =HashBiMap.newWithKeysValues(1, "1", 2, "2", 3, "3");MutableBiMap\<String, Integer\> inverse = biMap.inverse();Assert.assertEquals("1", biMap.get(1));Assert.assertEquals(Integer.valueOf(1), inverse.get("1"));Assert.assertTrue(inverse.containsKey("3"));Assert.assertEquals(Integer.valueOf(2), inverse.put("2", 4));
put()
MutableBiMap.put()
behaves likeMap.put()
on a regular map, except it throws when a duplicate value is added.MutableBiMap\<Integer, String\> biMap = HashBiMap.newMap(); biMap.put(1, "1"); // behaves like a regular put()biMap.put(1, "1"); // no effectbiMap.put(2, "1"); // throws IllegalArgumentException
๐ฎ forcePut()
๐ This behaves like
MutableBiMap.put()
, but it silently removes the map entry with the same value before putting the key-value pair in the map.MutableBiMap\<Integer, String\> biMap = HashBiMap.newMap(); biMap.forcePut(1, "1"); // behaves like a regular put()biMap.forcePut(1, "1"); // no effectbiMap.put(1, "2"); // replaces the [1,"1"] pair with [1, "2"]biMap.forcePut(2, "2"); // removes the [1, "2"] pair before puttingAssert.assertFalse(biMap.containsKey(1));Assert.assertEquals(HashBiMap.newWithKeysValues(2, "2"), biMap);
โก๏ธ Optimize HashBag by delegating to ObjectIntHashMap
HashBag
now delegates toObjectIntHashMap<K>
instead of aMutableMap<K, Counter>
. This saves memory by eliminating theCounter
wrapper objects.Functions.chain()
The
Functions.chain<primitive>()
methods are similar toFunctions.chain()
, but they take a primitive function as the second argument. There are variants for all eight primitives:- chainBoolean()
- chainByte()
- chainChar()
- chainDouble()
- chainInt()
- chainFloat()
- chainLong()
- chainShort()