Hidden Treasures of Eclipse collections – 2019 edition
Eclipse Collections is an open source Java Collections framework. In this blog I am going to demonstrate five lesser known features of the framework. I published a similar blog in last year’s Java Advent Calendar. Please refer to the resources at the end of the blog for more information about the framework.
1. countBy()
: When you want to find the count of a particular object you can use the countBy()
API to get a Bag. The purpose of a Bag is to maintain mapping of an object to the count. A Bag can be used to query the count of an item in O(1)
time. Bag also provides additional helpful API which helps with counting. Learn more about Bag data structure in this blog.
01 02 03 04 05 06 07 08 09 10 11 12 | @Test public void countBy() { MutableList<String> strings = Lists.mutable.with( "A" , "B" , "C" , "A" , "B" , "A" ); Bag<String> stringToCount = strings.countBy(each -> each); assertEquals( 3 , stringToCount.occurrencesOf( "A" )); assertEquals( 2 , stringToCount.occurrencesOf( "B" )); assertEquals( 1 , stringToCount.occurrencesOf( "C" )); assertEquals( 3 , stringToCount.sizeDistinct()); assertEquals( 6 , stringToCount.size()); } |
2. reject()
: When you want to choose the elements which do not satisfy a predicate you can use the reject()
API. This API is provided for enhanced readability and to make it intuitive to developers. You can use reject()
in place of using a select()
and negation of a boolean condition. In essence all the elements which do not return true
for a boolean condition will be chosen when using reject()
. The output of reject(BooleanCondition)
is the same as what you will get by doing a select(!someBooleanCondition)
.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 | @Test public void reject() { MutableList<Integer> numbers = Lists.mutable.with( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ); MutableList<Integer> odds = numbers.reject(num -> num % 2 == 0 ); // reject pattern used to find odd numbers. // Notice there is no negation in the predicate. assertEquals(Lists.mutable.with( 1 , 3 , 5 , 7 , 9 ), odds); MutableList<Integer> oddsUsingSelect = numbers.select(num -> num % 2 != 0 ); assertEquals(odds, oddsUsingSelect); } |
3. makeString()
: When you want a configurable string representation of a RichIterable
you can use makeString()
. If you use makeString()
without a delimiter, then a default delimiter of "comma space" ( ", " )
is used. If you want a specific delimiter you can pass it to makeString()
and the output string will have the string representation where every element separated by a delimiter. The delimiter is not used if the size of Iterable
is 1.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 | @Test public void makeString() { MutableList<Integer> nums = Lists.mutable.with( 1 , 2 , 3 ); assertEquals( "[1, 2, 3]" , nums.toString()); // Notice the difference: toString() vs makeString(). // the ", " delimiter is used by default assertEquals( "1, 2, 3" , nums.makeString()); // Delimiter of choice can be passed assertEquals( "1;2;3" , nums.makeString( ";" )); MutableList<Integer> singleElement = Lists.mutable.with( 1 ); // Delimiter is not used for size = 1 assertEquals( "1" , singleElement.makeString()); assertEquals( "1" , singleElement.makeString( ";" )); } |
4. zip()
: When you want to stitch two OrderedIterable
s together you can use zip()
. The zip()
API operates on two OrderedIterable
s and stitches them such that you get an OrderedIterable
of Pair
of elements. In the Pair
, the first of Pair
is the element from first OrderedIterable
and the second of Pair
is the element from second OrderedIterable
. In case the OrderedIterable
s are of different sizes then the excess elements from the longer OrderedIterable
are ignored. The output of zip()
is an OrderedIterable
of the same size as the smaller OrderedIterable
.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | @Test public void zip() { MutableList<Integer> nums = Lists.mutable.with( 1 , 2 , 3 ); MutableList<String> strings = Lists.mutable.with( "A" , "B" , "C" ); assertEquals( Lists.mutable.with(Tuples.pair( 1 , "A" ), Tuples.pair( 2 , "B" ), Tuples.pair( 3 , "C" )), nums.zip(strings)); assertEquals( Lists.mutable.with(Tuples.pair( "A" , 1 ), Tuples.pair( "B" , 2 ), Tuples.pair( "C" , 3 )), strings.zip(nums)); MutableList<Integer> numsSmallerSize = Lists.mutable.with( 1 ); assertEquals( Lists.mutable.with(Tuples.pair( 1 , "A" )), numsSmallerSize.zip(strings)); assertEquals( Lists.mutable.with(Tuples.pair( "A" , 1 )), strings.zip(numsSmallerSize)); MutableList<String> stringsSmallerSize = Lists.mutable.with( "A" , "B" ); assertEquals( Lists.mutable.with(Tuples.pair( 1 , "A" ), Tuples.pair( 2 , "B" )), nums.zip(stringsSmallerSize)); assertEquals( Lists.mutable.with(Tuples.pair( "A" , 1 ), Tuples.pair( "B" , 2 )), stringsSmallerSize.zip(nums)); } |
5. corresponds()
: When you want to find if all elements of two OrderedIterable
s are equal according to a Predicate
you can use the corresponds()
API. The corresponds()
API operates by first checking if the two OrderedIterable
s have the same size, if they have the same size then corresponding elements of both the OrderedIterable
s are evaluated using the Predicate
passed to corresponds()
. If the size of OrderedIterable
s is equal and the Predicate
returns true
for all elements then corresponds()
returns true
. If the size of OrderedIterable
s is not equal or the Predicate
returns false
for any element then corresponds()
returns false
.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 | @Test public void corresponds() { MutableList<Integer> lhs1 = Lists.mutable.with( 1 , 2 , 3 ); MutableList<Integer> rhs1 = Lists.mutable.with( 1 , 2 , 3 ); assertTrue(lhs1.corresponds(rhs1, Integer::equals)); MutableList<Integer> lhs2 = Lists.mutable.with( 1 , 2 , 3 ); MutableList<Integer> rhs2 = Lists.mutable.with( 2 , 4 , 6 ); assertTrue( lhs2.corresponds(rhs2, (lhs, rhs) -> rhs == 2 * lhs)); assertFalse( lhs2.corresponds(rhs2, (lhs, rhs) -> rhs == lhs * lhs)); assertFalse(lhs2.corresponds(rhs2, Integer::equals)); MutableList<Integer> lhs3 = Lists.mutable.with( 1 , 2 ); MutableList<Integer> rhs3 = Lists.mutable.with( 1 , 2 , 3 ); assertFalse(lhs3.corresponds(rhs3, Integer::equals)); } |
Eclipse Collections Resources:
Eclipse Collections comes with it’s own implementations of List, Set and Map. It also has additional data structures like Multimap, Bag and an entire Primitive Collections hierarchy. Each of our collections have a fluent and rich API for commonly required iteration patterns.
- Website
- Source code on GitHub (Make sure to star Repository)
- Contribution Guide
- Reference Guide
- Hidden Treasures of Eclipse Collections 2018 Edition
Published on Java Code Geeks with permission by Nikhil Nanivadekar, partner at our JCG program. See the original article here: Hidden Treasures of Eclipse collections – 2019 edition Opinions expressed by Java Code Geeks contributors are their own. |