SlideShare a Scribd company logo
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Donald Raab
Collections.compare(() -> {
JDK; Apache; Eclipse; Guava...});
Leonardo Lima
Nikhil J. Nanivadekar
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
About the Speakers
Donald Raab
• Husband and Father
• Managing Director at BNY Mellon in New Jersey
• Creator of Eclipse Collections
• Member of JSR 335 Expert Group (Lambdas 4 Java)
• Presenter at JavaOne, EclipseCon, JVM Language Summit, GIDS
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
About the Speakers
Leonardo Lima
• Computer engineer, server & embedded sw developer
• From São Paulo, Brasil, currently in Austin, TX
• CTO at V2COM
• Spec Lead – JSR363 – Units of Measurement
• Representative at JCP Executive Committee
[about.me/leomrlima]
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Nikhil J. Nanivadekar
• Mechanical Engineer
• Software developer
• Vice President Technology at Goldman Sachs
• From Pune, India, currently in Salt Lake City, Utah
About the Speakers
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
java.util
Collections
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
java.util Collections
Java Collection Framework has been around since 1998/JDK 1.2. Very
basic but critical collection support for Java.
Interfaces: Maps and Collections (List, Set, Queue, Deque)
Implementations: Basic and Concurrent versions of the interfaces,
sorted and concurrent as well
Algorithms: Sorting, Shuffling, Routine Data Manipulation, Searching,
Composition
Best way to get started is using the simple and concurrent tutorials
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Java 2
1998
• Interfaces
• Collection
• List
• Set
• Map
• SortedSet
• SortedMap
Java 5
2005
• Generics
• For-each loop
• Interfaces
• Iterable
• Queue
• ConcurrentMap
• BlockingQueue
Java 6
2006
•Interfaces
•NavigableSet
•NavigableMap
•Deque
•BlockingDeque
•ConcurrentNavigableMap
Java 7
2011
• Interfaces
• TransferQueue
Java 8
2014
• Lambdas
• Method Refs
• Default Methods
• Interfaces
• BaseStream
• Stream
• IntStream
• LongStream
• DoubleStream
• Collector
• Spliterator
• PrimitiveIterator
Java Collections Framework
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
!java.util
Collections?
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
!java.util Collections
We’re considering 4 collection frameworks, in alphabetical order:
Apache Commons Collection
Eclipse Collections (Formerly GS Collections)
Google Guava
Javaslang
(links to their user guide/documentation!)
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Collection Framework Timelines
Java 2
1998
• Jakarta
Collections 1.0
• 2001
• Apache
Collections 3.0
• 2004
Java 6
2006
• Google
Collections 1.0
• Dec. 2009
Java 7
2011
• Google Guava
10.0
• Sept. 2011
• GS Collections
1.0
• Jan. 2012
• Apache
Collections 4.0
• Nov. 2013
Java 8
2014
• Javaslang 1.0
• Mar. 2014
• Apache Collections
4.1
• Nov. 2015
• Eclipse Collections
7.0
• Jan. 2016
• Eclipse Collections
8.0 (Java 8)
• Sept. 2016
• Google Guava 20.0
• Oct. 2016
• Javaslang 2.1a
• Nov. 2016
March
2017
• Google Guava
21.0 (Java 8)
• Jan. 2017
• Eclipse
Collections 8.1
• Mar. 2017
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Collections.
compare();
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Use Case – Deck of Cards
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Problem Statement – Deck of Cards
1. Create Deck of Cards
• Store Cards in an “Immutable” SortedSet (Cartesian product of Suit x Rank)
• Group the cards by Suit in an “Immutable” SortedSet “Multimap” (Group By)
2. Get the number of cards
• Count By Suit returning “Multiset” or “Bag”
• Count By Rank returning “Multiset” or “Bag”
3. Deal five hands of five cards each
• Return the cards as an “Immutable” List of five Sets of five cards
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Performance Benchmarks
• JMH - Java Microbenchmark Harness
• http://openjdk.java.net/projects/code-tools/jmh/
• Measure Reported – Operations per second
• Bigger numbers are better
• 4 Core Intel I7, 50 Warm-up iterations, 30 measurement iterations,
two forks
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Problem Statement – Deck of Cards
1. Create Deck of Cards
• Store Cards in an “Immutable” SortedSet (Cartesian product of Suit x Rank)
• Group the cards by Suit in an “Immutable” SortedSet “Multimap” (Group By)
2. Get the number of cards
• Count By Suit returning “Multiset” or “Bag”
• Count By Rank returning “Multiset” or “Bag”
3. Deal five hands of five cards each
• Return the cards as an “Immutable” List of five Sets of five cards
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Performance Test - Deck of Cards
102,037
79,343 76,982
56,224
91,017
0
20,000
40,000
60,000
80,000
100,000
120,000
Scoreops/s
Framework
Deck of Cards
Apache EC Guava Javaslang JDK
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public class JDK8DeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, SortedSet<Card>> cardsBySuit;
A Deck of Cards – Only the Types
public class ApacheCommonsDeckOfCards {
private SortedSet<Card> cards;
private MultiValuedMap<Suit, Card> cardsBySuit;
public class EclipseCollectionsDeckOfCards {
private ImmutableSortedSet<Card> cards;
private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit;
public class GoogleGuavaDeckOfCards {
private ImmutableSortedSet<Card> cards;
private ImmutableSetMultimap<Suit, Card> cardsBySuit;
public class JavaSlangDeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, ? extends SortedSet<Card>> cardsBySuit;
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public class JDK8DeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, SortedSet<Card>> cardsBySuit;
A Deck of Cards – Only the Types
public class ApacheCommonsDeckOfCards {
private SortedSet<Card> cards;
private MultiValuedMap<Suit, Card> cardsBySuit;
public class EclipseCollectionsDeckOfCards {
private ImmutableSortedSet<Card> cards;
private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit;
public class GoogleGuavaDeckOfCards {
private ImmutableSortedSet<Card> cards;
private ImmutableSetMultimap<Suit, Card> cardsBySuit;
public class JavaSlangDeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, ? extends SortedSet<Card>> cardsBySuit;
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public class JDK8DeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, SortedSet<Card>> cardsBySuit;
A Deck of Cards – Only the Types
public class ApacheCommonsDeckOfCards {
private SortedSet<Card> cards;
private MultiValuedMap<Suit, Card> cardsBySuit;
public class EclipseCollectionsDeckOfCards {
private ImmutableSortedSet<Card> cards;
private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit;
public class GoogleGuavaDeckOfCards {
private ImmutableSortedSet<Card> cards;
private ImmutableSetMultimap<Suit, Card> cardsBySuit;
public class JavaSlangDeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, ? extends SortedSet<Card>> cardsBySuit;
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public class JDK8DeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, SortedSet<Card>> cardsBySuit;
A Deck of Cards – Only the Types
public class ApacheCommonsDeckOfCards {
private SortedSet<Card> cards;
private MultiValuedMap<Suit, Card> cardsBySuit;
public class EclipseCollectionsDeckOfCards {
private ImmutableSortedSet<Card> cards;
private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit;
public class GoogleGuavaDeckOfCards {
private ImmutableSortedSet<Card> cards;
private ImmutableSetMultimap<Suit, Card> cardsBySuit;
public class JavaSlangDeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, ? extends SortedSet<Card>> cardsBySuit;
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public class JDK8DeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, SortedSet<Card>> cardsBySuit;
A Deck of Cards – Only the Types
public class ApacheCommonsDeckOfCards {
private SortedSet<Card> cards;
private MultiValuedMap<Suit, Card> cardsBySuit;
public class EclipseCollectionsDeckOfCards {
private ImmutableSortedSet<Card> cards;
private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit;
public class GoogleGuavaDeckOfCards {
private ImmutableSortedSet<Card> cards;
private ImmutableSetMultimap<Suit, Card> cardsBySuit;
public class JavaSlangDeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, ? extends SortedSet<Card>> cardsBySuit;
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public class JDK8DeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, SortedSet<Card>> cardsBySuit;
A Deck of Cards – Only the Types
public class ApacheCommonsDeckOfCards {
private SortedSet<Card> cards;
private MultiValuedMap<Suit, Card> cardsBySuit;
public class EclipseCollectionsDeckOfCards {
private ImmutableSortedSet<Card> cards;
private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit;
public class GoogleGuavaDeckOfCards {
private ImmutableSortedSet<Card> cards;
private ImmutableSetMultimap<Suit, Card> cardsBySuit;
public class JavaSlangDeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, ? extends SortedSet<Card>> cardsBySuit;
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Problem Statement – Deck of Cards
1. Create Deck of Cards
• Store Cards in an “Immutable” SortedSet (Cartesian product of Suit x Rank)
• Group the cards by Suit in an “Immutable” SortedSet “Multimap” (Group By)
2. Get the number of cards
• Count By Suit returning “Multiset” or “Bag”
• Count By Rank returning “Multiset” or “Bag”
3. Deal five hands of five cards each
• Return the cards as an “Immutable” List of five Sets of five cards
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Shared Code – Cartesian Product
public static Stream<Card> streamCards() {
return Card.cartesianProduct(
EnumSet.allOf(Rank.class),
EnumSet.allOf(Suit.class),
Card::new);
}
private static <A, B, C> Stream<C> cartesianProduct(
Set<A> set1,
Set<B> set2,
Function2<A, B, C> function) {
return set1.stream().flatMap(first ->
set2.stream().map(second ->
function.apply(first, second)));
}
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Performance Test - Cartesian Product
185,087
203,660
465,999
127,439
114,634
0
50,000
100,000
150,000
200,000
250,000
300,000
350,000
400,000
450,000
500,000
Scoreops/s
Framework
Cartesian Product
Apache EC Guava Javaslang JDK
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public class JDK8DeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, SortedSet<Card>> cardsBySuit;
public JDK8DeckOfCards() {
this.cards = Card.streamCards()
.collect(Collectors.collectingAndThen(
Collectors.toCollection(TreeSet::new),
Collections::unmodifiableSortedSet));
this.cardsBySuit =
Collections.unmodifiableMap(
this.cards.stream().collect(Collectors.groupingBy(
Card::getSuit,
Collectors.mapping(Function.identity(),
Collectors.collectingAndThen(
Collectors.toCollection(TreeSet::new),
Collections::unmodifiableSortedSet)))));
}
JDK Collections – Cartesian Product
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
this.cards = Card.streamCards()
.collect(Collectors.collectingAndThen(
Collectors.toCollection(TreeSet::new),
Collections::unmodifiableSortedSet));
JDK Collections – Cartesian Product
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public class ApacheCommonsDeckOfCards {
private SortedSet<Card> cards;
private MultiValuedMap<Suit, Card> cardsBySuit;
public ApacheCommonsDeckOfCards() {
this.cards = Card.streamCards()
.collect(Collectors.collectingAndThen(
Collectors.toCollection(TreeSet::new),
Collections::unmodifiableSortedSet));
SetValuedMap<Suit, Card> cbs = MultiMapUtils.newSetValuedHashMap();
this.cards.forEach(card -> cbs.put(card.getSuit(), card));
this.cardsBySuit = MultiMapUtils.unmodifiableMultiValuedMap(cbs);
}
Apache Collections – Cartesian Product
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
this.cards = Card.streamCards()
.collect(Collectors.collectingAndThen(
Collectors.toCollection(TreeSet::new),
Collections::unmodifiableSortedSet));
Apache Collections – Cartesian Product
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public class EclipseCollectionsDeckOfCards {
private ImmutableSortedSet<Card> cards;
private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit;
public EclipseCollectionsDeckOfCards() {
this.cards = SortedSets.immutable.with(
Card.streamCards()
.toArray(Card[]::new));
this.cardsBySuit = this.cards.groupBy(Card::getSuit);
}
Eclipse Collections – Cartesian Product
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
this.cards = SortedSets.immutable.with(
Card.streamCards()
.toArray(Card[]::new));
Eclipse Collections – Cartesian Product
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public class GoogleGuavaDeckOfCards {
private ImmutableSortedSet<Card> cards;
private ImmutableSetMultimap<Suit, Card> cardsBySuit;
public GoogleGuavaDeckOfCards() {
this.cards = Card.streamCards()
.collect(ImmutableSortedSet.toImmutableSortedSet(
Comparator.naturalOrder()));
ImmutableSetMultimap.Builder<Suit, Card> builder =
new ImmutableSetMultimap.Builder<Suit, Card>()
.orderValuesBy(Comparator.naturalOrder());
this.cards.forEach(card -> builder.put(card.getSuit(), card));
this.cardsBySuit = builder.build();
}
Google Guava – Cartesian Product
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
this.cards = Card.streamCards()
.collect(
ImmutableSortedSet.toImmutableSortedSet(
Comparator.naturalOrder()));
Google Guava – Cartesian Product
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public class JavaSlangDeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, ? extends SortedSet<Card>> cardsBySuit;
public JavaSlangDeckOfCards() {
this.cards = Card.streamCards()
.collect(TreeSet.collector());
this.cardsBySuit = this.cards.groupBy(Card::getSuit);
}
Javaslang – Cartesian Product
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
this.cards = Card.streamCards()
.collect(TreeSet.collector());
Javaslang – Cartesian Product
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Problem Statement – Deck of Cards
1. Create Deck of Cards
• Store Cards in an “Immutable” SortedSet (Cartesian product of Suit x Rank)
• Group the cards by Suit in an “Immutable” SortedSet “Multimap” (Group By)
2. Get the number of cards
• Count By Suit returning “Multiset” or “Bag”
• Count By Rank returning “Multiset” or “Bag”
3. Deal five hands of five cards each
• Return the cards as an “Immutable” List of five Sets of five cards
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Performance Test - groupBy
540,396
183,848
231,321
176,412
353,651
-
100,000
200,000
300,000
400,000
500,000
600,000
Scoreops/s
Framework
groupBy
Apache EC Guava Javaslang JDK
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public class JDK8DeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, SortedSet<Card>> cardsBySuit;
public JDK8DeckOfCards() {
this.cards = Card.streamCards()
.collect(Collectors.collectingAndThen(
Collectors.toCollection(TreeSet::new),
Collections::unmodifiableSortedSet));
this.cardsBySuit =
Collections.unmodifiableMap(
this.cards.stream().collect(Collectors.groupingBy(
Card::getSuit,
Collectors.mapping(Function.identity(),
Collectors.collectingAndThen(
Collectors.toCollection(TreeSet::new),
Collections::unmodifiableSortedSet)))));
}
JDK Collections – Group By
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
this.cardsBySuit =
Collections.unmodifiableMap(
this.cards.stream().collect(Collectors.groupingBy(
Card::getSuit,
Collectors.mapping(Function.identity(),
Collectors.collectingAndThen(
Collectors.toCollection(TreeSet::new),
Collections::unmodifiableSortedSet)))
));
JDK Collections – Group By
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public class ApacheCommonsDeckOfCards {
private SortedSet<Card> cards;
private MultiValuedMap<Suit, Card> cardsBySuit;
public ApacheCommonsDeckOfCards() {
this.cards = Card.streamCards()
.collect(Collectors.collectingAndThen(
Collectors.toCollection(TreeSet::new),
Collections::unmodifiableSortedSet));
SetValuedMap<Suit, Card> cbs = MultiMapUtils.newSetValuedHashMap();
this.cards.forEach(card -> cbs.put(card.getSuit(), card));
this.cardsBySuit = MultiMapUtils.unmodifiableMultiValuedMap(cbs);
}
Apache Collections – Group By
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
SetValuedMap<Suit, Card> cbs =
MultiMapUtils.newSetValuedHashMap();
this.cards.forEach(card ->
cbs.put(card.getSuit(), card));
this.cardsBySuit =
MultiMapUtils.unmodifiableMultiValuedMap(cbs);
Apache Collections – Group By
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public class EclipseCollectionsDeckOfCards {
private ImmutableSortedSet<Card> cards;
private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit;
public EclipseCollectionsDeckOfCards() {
this.cards = SortedSets.immutable.with(
Card.streamCards()
.toArray(Card[]::new));
this.cardsBySuit = this.cards.groupBy(Card::getSuit);
}
Eclipse Collections – Group By
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
this.cardsBySuit =
this.cards.groupBy(Card::getSuit);
Eclipse Collections – Group By
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public class GoogleGuavaDeckOfCards {
private ImmutableSortedSet<Card> cards;
private ImmutableSetMultimap<Suit, Card> cardsBySuit;
public GoogleGuavaDeckOfCards() {
this.cards = Card.streamCards()
.collect(ImmutableSortedSet.toImmutableSortedSet(
Comparator.naturalOrder()));
ImmutableSetMultimap.Builder<Suit, Card> builder =
new ImmutableSetMultimap.Builder<Suit, Card>()
.orderValuesBy(Comparator.naturalOrder());
this.cards.forEach(card -> builder.put(card.getSuit(), card));
this.cardsBySuit = builder.build();
}
Google Guava – Group By
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
ImmutableSetMultimap.Builder<Suit, Card> builder =
new ImmutableSetMultimap.Builder<Suit, Card>()
.orderValuesBy(Comparator.naturalOrder());
this.cards.forEach(card ->
builder.put(card.getSuit(), card));
this.cardsBySuit = builder.build();
Google Guava – Group By
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public class JavaSlangDeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, ? extends SortedSet<Card>> cardsBySuit;
public JavaSlangDeckOfCards() {
this.cards = Card.streamCards()
.collect(TreeSet.collector());
this.cardsBySuit = this.cards.groupBy(Card::getSuit);
}
Javaslang – Group By
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
this.cardsBySuit =
this.cards.groupBy(Card::getSuit);
Javaslang – Group By
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Performance Test - Deck of Cards
102,037
79,343 76,982
56,224
91,017
0
20,000
40,000
60,000
80,000
100,000
120,000Scoreops/s
Framework
Deck of Cards
Apache EC Guava Javaslang JDK
540,396
183,848
231,321
176,412
353,651
-
200,000
400,000
600,000
Scoreops/s
Framework
groupBy
Apache EC Guava Javaslang JDK
185,087 203,660
465,999
127,439 114,634
0
200,000
400,000
600,000
Scoreops/s
Framework
Cartesian Product
Apache EC Guava Javaslang JDK
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Problem Statement – Deck of Cards
1. Create Deck of Cards
• Store Cards in an “Immutable” SortedSet (Cartesian product of Suit x Rank)
• Group the cards by Suit in an “Immutable” SortedSet “Multimap” (Group By)
2. Get the number of cards
• Count By Suit returning “Multiset” or “Bag”
• Count By Rank returning “Multiset” or “Bag”
3. Deal five hands of five cards each
• Return the cards as an “Immutable” List of five Sets of five cards
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Performance Test - countsBySuit
706,272
1,096,527
533,728
440,786
724,526
0
200,000
400,000
600,000
800,000
1,000,000
1,200,000
Scoreops/s
Framework
Apache EC Guava Javaslang JDK
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Performance Test - countsByRank
539,252
827,986
444,832
390,134
591,869
0
100,000
200,000
300,000
400,000
500,000
600,000
700,000
800,000
900,000
Scoreops/s
Framework
Apache EC Guava Javaslang JDK
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public Map<Suit, Long> countsBySuit() {
return this.cards.stream()
.collect(Collectors.groupingBy(
Card::getSuit, Collectors.counting()));
}
public Map<Rank, Long> countsByRank() {
return this.cards.stream()
.collect(Collectors.groupingBy(
Card::getRank, Collectors.counting()));
}
JDK Collections – Count By
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public Bag<Suit> countsBySuit() {
return this.cards.stream()
.map(Card::getSuit)
.collect(Collectors.toCollection(
HashBag::new));
}
public MultiSet<Rank> countsByRank() {
return this.cards.stream()
.map(Card::getRank)
.collect(Collectors.toCollection(
HashMultiSet::new));
}
Apache Collections – Count By
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public Bag<Suit> countsBySuit() {
return this.cards.asLazy()
.collect(Card::getSuit)
.toBag();
}
public Bag<Rank> countsByRank() {
return this.cards.asLazy()
.collect(Card::getRank)
.toBag();
}
Eclipse Collections – Count By
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public Multiset<Suit> countsBySuit() {
return this.cards.stream()
.map(Card::getSuit)
.collect(Collectors.toCollection(
HashMultiset::create));
}
public Multiset<Rank> countsByRank() {
return this.cards.stream()
.map(Card::getRank)
.collect(Collectors.toCollection(
HashMultiset::create));
}
Google Guava – Count By
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
public java.util.Map<Suit, Long> countsBySuit() {
return this.cards.collect(
Collectors.groupingBy(
Card::getSuit,
Collectors.counting()));
}
public java.util.Map<Rank, Long> countsByRank() {
return this.cards.collect(
Collectors.groupingBy(
Card::getRank,
Collectors.counting()));
}
Javaslang – Count By
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Problem Statement – Deck of Cards
1. Create Deck of Cards
• Store Cards in an “Immutable” SortedSet (Cartesian product of Suit x Rank)
• Group the cards by Suit in an “Immutable” SortedSet “Multimap” (Group By)
2. Get the number of cards
• Count By Suit returning “Multiset” or “Bag”
• Count By Rank returning “Multiset” or “Bag”
3. Deal five hands of five cards each
• Return the cards as an “Immutable” List of five Sets of five cards
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Performance Test – Deal Hands
291,488
502,448
305,673
372,466
300,975
0
100,000
200,000
300,000
400,000
500,000
600,000
Scoreops/s
Framework
Apache EC Guava Javaslang JDK
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
JDK Collections – Deal Hands
public List<Set<Card>> dealHands(
Deque<Card> shuffled,
int hands,
int cardsPerHand) {
return IntStream.range(0, hands)
.mapToObj(i -> this.deal(shuffled, cardsPerHand))
.collect(Collectors.collectingAndThen(
Collectors.toList(),
Collections::unmodifiableList));
}
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Apache Collections – Deal Hands
public List<Set<Card>> dealHands(
Deque<Card> shuffled,
int hands,
int cardsPerHand) {
return IntStream.range(0, hands)
.mapToObj(i -> this.deal(shuffled, cardsPerHand))
.collect(Collectors.collectingAndThen(
Collectors.toList(),
Collections::unmodifiableList));
}
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Eclipse Collections – Deal Hands
public ImmutableList<Set<Card>> dealHands(
MutableStack<Card> shuffled,
int hands,
int cardsPerHand) {
return IntInterval.oneTo(hands)
.collect(i -> this.deal(shuffled, cardsPerHand));
}
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Google Guava – Deal Hands
public ImmutableList<Set<Card>> dealHands(
Deque<Card> shuffled,
int hands,
int cardsPerHand) {
return IntStream.range(0, hands)
.mapToObj(i -> this.deal(shuffled, cardsPerHand))
.collect(ImmutableList.toImmutableList());
}
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Javaslang – Deal Hands
public List<Set<Card>> dealHands(
Stack<Card> shuffled,
int hands,
int cardsPerHand) {
List<Set<Card>> list = List.empty();
for (int i = 0; i < hands; i++) {
Tuple2<Set<Card>, ? extends Stack<Card>> tuple2 =
this.deal(shuffled, cardsPerHand);
shuffled = tuple2._2();
list = list.append(tuple2._1());
}
return list;
}
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Feature JDK Apache Guava Eclipse Javaslang 1st, 2nd, 3rd
List, Set, Map ✔  ✖ ✔  JDK, EC, JS
Multiset / Bag ✖ ✔ ✔ ✔ ✖ GG, EC, AC
Multimap ✖ ✔ ✔ ✔ ✔ GG, EC, AC
BiMap ✖ ✔ ✔ ✔ ✖ GG, EC, AC
Stack ✔  ✖ ✔ ✔ EC, JDK, JS
Tree / Trie ✖ ✔ ✖ ✖ ✔ JS, AC
Table ✖ ✖ ✔ ✖ ✖ GG
Additional Types ✔ ✔ ✔   AC, JDK, GG
Immutable? ✖ ✖ ✔ ✔ ✔ JS, EC, GG
Primitives?  ✖  ✔ ✖ EC, JDK, GG
Fluent API    ✔ ✔ EC, JS, JDK
(E), (L), (S), (P)* , ✔, ✔, ✔ , , ✔, ✖ ✖, , ✔, ✖ ✔, ✔, ✔, ✔ ✔, ✔, ✔, ✖ EC, JDK, JS
Collection Framework Comparison
*(E)ager, (L)azy, (S)erial, (P)arallel – Functional API
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Links
The Collections Compare Project
https://github.com/nikhilnanivadekar/CollectionsCompare
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Q & A
#CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade
Thanks!

More Related Content

PPTX
Collections.compare(JDK, Eclipse, Guava, Apache...); GIDS 2017
PPTX
Collections.compare(() -> JDK; Apache; Eclipse, Guava...});
PDF
JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]
PPTX
10 Strategies for Developing Reliable Jakarta EE & MicroProfile Applications ...
PDF
Scala Frustrations
PDF
Solid and Sustainable Development in Scala
PDF
Solid And Sustainable Development in Scala
PPTX
Modules in Java? Finally! (OpenJDK 9 Jigsaw, JSR376)
Collections.compare(JDK, Eclipse, Guava, Apache...); GIDS 2017
Collections.compare(() -> JDK; Apache; Eclipse, Guava...});
JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]
10 Strategies for Developing Reliable Jakarta EE & MicroProfile Applications ...
Scala Frustrations
Solid and Sustainable Development in Scala
Solid And Sustainable Development in Scala
Modules in Java? Finally! (OpenJDK 9 Jigsaw, JSR376)

Similar to Collections.compare(JDK, Eclipse, Guava, Apache...); DevoxxUS 2017 (20)

PDF
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
PDF
JavaOne 2017 - JNoSQL: The Definitive Solution for Java and NoSQL Database [C...
PDF
Java 9 preview
PDF
What we can expect from Java 9 by Ivan Krylov
KEY
JavaScript For People Who Don't Code
PDF
Where Django Caching Bust at the Seams
PPTX
Building Deep Learning Workflows with DL4J
PPTX
Preparing for java 9 modules upload
PDF
DIとトレイとによるAndroid開発の効率化
PDF
The cost of learning - advantage of mixer2
PPTX
Brightstar DB
PDF
Inside the JVM - Follow the white rabbit!
PDF
Devoxx UK quickie talk about walkmod
KEY
Accessible UIs with jQuery and Infusion
PPT
JavaFX - Next Generation Java UI
PPT
Introducing Scala to your Ruby/Java Shop : My experiences at IGN
PDF
How can your applications benefit from Java 9?
PDF
Polyglot Adventures for the Modern Java Developer #javaone2017
PDF
Polyglot Adventures for the Modern Java Developer
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
JavaOne 2017 - JNoSQL: The Definitive Solution for Java and NoSQL Database [C...
Java 9 preview
What we can expect from Java 9 by Ivan Krylov
JavaScript For People Who Don't Code
Where Django Caching Bust at the Seams
Building Deep Learning Workflows with DL4J
Preparing for java 9 modules upload
DIとトレイとによるAndroid開発の効率化
The cost of learning - advantage of mixer2
Brightstar DB
Inside the JVM - Follow the white rabbit!
Devoxx UK quickie talk about walkmod
Accessible UIs with jQuery and Infusion
JavaFX - Next Generation Java UI
Introducing Scala to your Ruby/Java Shop : My experiences at IGN
How can your applications benefit from Java 9?
Polyglot Adventures for the Modern Java Developer #javaone2017
Polyglot Adventures for the Modern Java Developer
Ad

Recently uploaded (20)

PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PPTX
Big Data Technologies - Introduction.pptx
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PPTX
Cloud computing and distributed systems.
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
A comparative analysis of optical character recognition models for extracting...
PPT
Teaching material agriculture food technology
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PPTX
sap open course for s4hana steps from ECC to s4
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Approach and Philosophy of On baking technology
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
gpt5_lecture_notes_comprehensive_20250812015547.pdf
Big Data Technologies - Introduction.pptx
“AI and Expert System Decision Support & Business Intelligence Systems”
Per capita expenditure prediction using model stacking based on satellite ima...
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Cloud computing and distributed systems.
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
A comparative analysis of optical character recognition models for extracting...
Teaching material agriculture food technology
Unlocking AI with Model Context Protocol (MCP)
NewMind AI Weekly Chronicles - August'25-Week II
sap open course for s4hana steps from ECC to s4
Mobile App Security Testing_ A Comprehensive Guide.pdf
Encapsulation_ Review paper, used for researhc scholars
Building Integrated photovoltaic BIPV_UPV.pdf
Approach and Philosophy of On baking technology
Dropbox Q2 2025 Financial Results & Investor Presentation
Ad

Collections.compare(JDK, Eclipse, Guava, Apache...); DevoxxUS 2017

  • 1. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Donald Raab Collections.compare(() -> { JDK; Apache; Eclipse; Guava...}); Leonardo Lima Nikhil J. Nanivadekar
  • 2. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade About the Speakers Donald Raab • Husband and Father • Managing Director at BNY Mellon in New Jersey • Creator of Eclipse Collections • Member of JSR 335 Expert Group (Lambdas 4 Java) • Presenter at JavaOne, EclipseCon, JVM Language Summit, GIDS
  • 3. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade About the Speakers Leonardo Lima • Computer engineer, server & embedded sw developer • From São Paulo, Brasil, currently in Austin, TX • CTO at V2COM • Spec Lead – JSR363 – Units of Measurement • Representative at JCP Executive Committee [about.me/leomrlima]
  • 4. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Nikhil J. Nanivadekar • Mechanical Engineer • Software developer • Vice President Technology at Goldman Sachs • From Pune, India, currently in Salt Lake City, Utah About the Speakers
  • 5. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade java.util Collections
  • 6. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade java.util Collections Java Collection Framework has been around since 1998/JDK 1.2. Very basic but critical collection support for Java. Interfaces: Maps and Collections (List, Set, Queue, Deque) Implementations: Basic and Concurrent versions of the interfaces, sorted and concurrent as well Algorithms: Sorting, Shuffling, Routine Data Manipulation, Searching, Composition Best way to get started is using the simple and concurrent tutorials
  • 7. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Java 2 1998 • Interfaces • Collection • List • Set • Map • SortedSet • SortedMap Java 5 2005 • Generics • For-each loop • Interfaces • Iterable • Queue • ConcurrentMap • BlockingQueue Java 6 2006 •Interfaces •NavigableSet •NavigableMap •Deque •BlockingDeque •ConcurrentNavigableMap Java 7 2011 • Interfaces • TransferQueue Java 8 2014 • Lambdas • Method Refs • Default Methods • Interfaces • BaseStream • Stream • IntStream • LongStream • DoubleStream • Collector • Spliterator • PrimitiveIterator Java Collections Framework
  • 8. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade !java.util Collections?
  • 9. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade !java.util Collections We’re considering 4 collection frameworks, in alphabetical order: Apache Commons Collection Eclipse Collections (Formerly GS Collections) Google Guava Javaslang (links to their user guide/documentation!)
  • 10. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Collection Framework Timelines Java 2 1998 • Jakarta Collections 1.0 • 2001 • Apache Collections 3.0 • 2004 Java 6 2006 • Google Collections 1.0 • Dec. 2009 Java 7 2011 • Google Guava 10.0 • Sept. 2011 • GS Collections 1.0 • Jan. 2012 • Apache Collections 4.0 • Nov. 2013 Java 8 2014 • Javaslang 1.0 • Mar. 2014 • Apache Collections 4.1 • Nov. 2015 • Eclipse Collections 7.0 • Jan. 2016 • Eclipse Collections 8.0 (Java 8) • Sept. 2016 • Google Guava 20.0 • Oct. 2016 • Javaslang 2.1a • Nov. 2016 March 2017 • Google Guava 21.0 (Java 8) • Jan. 2017 • Eclipse Collections 8.1 • Mar. 2017
  • 11. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Collections. compare();
  • 12. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Use Case – Deck of Cards
  • 13. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Problem Statement – Deck of Cards 1. Create Deck of Cards • Store Cards in an “Immutable” SortedSet (Cartesian product of Suit x Rank) • Group the cards by Suit in an “Immutable” SortedSet “Multimap” (Group By) 2. Get the number of cards • Count By Suit returning “Multiset” or “Bag” • Count By Rank returning “Multiset” or “Bag” 3. Deal five hands of five cards each • Return the cards as an “Immutable” List of five Sets of five cards
  • 14. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Performance Benchmarks • JMH - Java Microbenchmark Harness • http://openjdk.java.net/projects/code-tools/jmh/ • Measure Reported – Operations per second • Bigger numbers are better • 4 Core Intel I7, 50 Warm-up iterations, 30 measurement iterations, two forks
  • 15. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Problem Statement – Deck of Cards 1. Create Deck of Cards • Store Cards in an “Immutable” SortedSet (Cartesian product of Suit x Rank) • Group the cards by Suit in an “Immutable” SortedSet “Multimap” (Group By) 2. Get the number of cards • Count By Suit returning “Multiset” or “Bag” • Count By Rank returning “Multiset” or “Bag” 3. Deal five hands of five cards each • Return the cards as an “Immutable” List of five Sets of five cards
  • 16. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Performance Test - Deck of Cards 102,037 79,343 76,982 56,224 91,017 0 20,000 40,000 60,000 80,000 100,000 120,000 Scoreops/s Framework Deck of Cards Apache EC Guava Javaslang JDK
  • 17. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public class JDK8DeckOfCards { private SortedSet<Card> cards; private Map<Suit, SortedSet<Card>> cardsBySuit; A Deck of Cards – Only the Types public class ApacheCommonsDeckOfCards { private SortedSet<Card> cards; private MultiValuedMap<Suit, Card> cardsBySuit; public class EclipseCollectionsDeckOfCards { private ImmutableSortedSet<Card> cards; private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit; public class GoogleGuavaDeckOfCards { private ImmutableSortedSet<Card> cards; private ImmutableSetMultimap<Suit, Card> cardsBySuit; public class JavaSlangDeckOfCards { private SortedSet<Card> cards; private Map<Suit, ? extends SortedSet<Card>> cardsBySuit;
  • 18. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public class JDK8DeckOfCards { private SortedSet<Card> cards; private Map<Suit, SortedSet<Card>> cardsBySuit; A Deck of Cards – Only the Types public class ApacheCommonsDeckOfCards { private SortedSet<Card> cards; private MultiValuedMap<Suit, Card> cardsBySuit; public class EclipseCollectionsDeckOfCards { private ImmutableSortedSet<Card> cards; private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit; public class GoogleGuavaDeckOfCards { private ImmutableSortedSet<Card> cards; private ImmutableSetMultimap<Suit, Card> cardsBySuit; public class JavaSlangDeckOfCards { private SortedSet<Card> cards; private Map<Suit, ? extends SortedSet<Card>> cardsBySuit;
  • 19. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public class JDK8DeckOfCards { private SortedSet<Card> cards; private Map<Suit, SortedSet<Card>> cardsBySuit; A Deck of Cards – Only the Types public class ApacheCommonsDeckOfCards { private SortedSet<Card> cards; private MultiValuedMap<Suit, Card> cardsBySuit; public class EclipseCollectionsDeckOfCards { private ImmutableSortedSet<Card> cards; private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit; public class GoogleGuavaDeckOfCards { private ImmutableSortedSet<Card> cards; private ImmutableSetMultimap<Suit, Card> cardsBySuit; public class JavaSlangDeckOfCards { private SortedSet<Card> cards; private Map<Suit, ? extends SortedSet<Card>> cardsBySuit;
  • 20. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public class JDK8DeckOfCards { private SortedSet<Card> cards; private Map<Suit, SortedSet<Card>> cardsBySuit; A Deck of Cards – Only the Types public class ApacheCommonsDeckOfCards { private SortedSet<Card> cards; private MultiValuedMap<Suit, Card> cardsBySuit; public class EclipseCollectionsDeckOfCards { private ImmutableSortedSet<Card> cards; private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit; public class GoogleGuavaDeckOfCards { private ImmutableSortedSet<Card> cards; private ImmutableSetMultimap<Suit, Card> cardsBySuit; public class JavaSlangDeckOfCards { private SortedSet<Card> cards; private Map<Suit, ? extends SortedSet<Card>> cardsBySuit;
  • 21. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public class JDK8DeckOfCards { private SortedSet<Card> cards; private Map<Suit, SortedSet<Card>> cardsBySuit; A Deck of Cards – Only the Types public class ApacheCommonsDeckOfCards { private SortedSet<Card> cards; private MultiValuedMap<Suit, Card> cardsBySuit; public class EclipseCollectionsDeckOfCards { private ImmutableSortedSet<Card> cards; private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit; public class GoogleGuavaDeckOfCards { private ImmutableSortedSet<Card> cards; private ImmutableSetMultimap<Suit, Card> cardsBySuit; public class JavaSlangDeckOfCards { private SortedSet<Card> cards; private Map<Suit, ? extends SortedSet<Card>> cardsBySuit;
  • 22. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public class JDK8DeckOfCards { private SortedSet<Card> cards; private Map<Suit, SortedSet<Card>> cardsBySuit; A Deck of Cards – Only the Types public class ApacheCommonsDeckOfCards { private SortedSet<Card> cards; private MultiValuedMap<Suit, Card> cardsBySuit; public class EclipseCollectionsDeckOfCards { private ImmutableSortedSet<Card> cards; private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit; public class GoogleGuavaDeckOfCards { private ImmutableSortedSet<Card> cards; private ImmutableSetMultimap<Suit, Card> cardsBySuit; public class JavaSlangDeckOfCards { private SortedSet<Card> cards; private Map<Suit, ? extends SortedSet<Card>> cardsBySuit;
  • 23. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Problem Statement – Deck of Cards 1. Create Deck of Cards • Store Cards in an “Immutable” SortedSet (Cartesian product of Suit x Rank) • Group the cards by Suit in an “Immutable” SortedSet “Multimap” (Group By) 2. Get the number of cards • Count By Suit returning “Multiset” or “Bag” • Count By Rank returning “Multiset” or “Bag” 3. Deal five hands of five cards each • Return the cards as an “Immutable” List of five Sets of five cards
  • 24. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Shared Code – Cartesian Product public static Stream<Card> streamCards() { return Card.cartesianProduct( EnumSet.allOf(Rank.class), EnumSet.allOf(Suit.class), Card::new); } private static <A, B, C> Stream<C> cartesianProduct( Set<A> set1, Set<B> set2, Function2<A, B, C> function) { return set1.stream().flatMap(first -> set2.stream().map(second -> function.apply(first, second))); }
  • 25. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Performance Test - Cartesian Product 185,087 203,660 465,999 127,439 114,634 0 50,000 100,000 150,000 200,000 250,000 300,000 350,000 400,000 450,000 500,000 Scoreops/s Framework Cartesian Product Apache EC Guava Javaslang JDK
  • 26. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public class JDK8DeckOfCards { private SortedSet<Card> cards; private Map<Suit, SortedSet<Card>> cardsBySuit; public JDK8DeckOfCards() { this.cards = Card.streamCards() .collect(Collectors.collectingAndThen( Collectors.toCollection(TreeSet::new), Collections::unmodifiableSortedSet)); this.cardsBySuit = Collections.unmodifiableMap( this.cards.stream().collect(Collectors.groupingBy( Card::getSuit, Collectors.mapping(Function.identity(), Collectors.collectingAndThen( Collectors.toCollection(TreeSet::new), Collections::unmodifiableSortedSet))))); } JDK Collections – Cartesian Product
  • 27. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade this.cards = Card.streamCards() .collect(Collectors.collectingAndThen( Collectors.toCollection(TreeSet::new), Collections::unmodifiableSortedSet)); JDK Collections – Cartesian Product
  • 28. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public class ApacheCommonsDeckOfCards { private SortedSet<Card> cards; private MultiValuedMap<Suit, Card> cardsBySuit; public ApacheCommonsDeckOfCards() { this.cards = Card.streamCards() .collect(Collectors.collectingAndThen( Collectors.toCollection(TreeSet::new), Collections::unmodifiableSortedSet)); SetValuedMap<Suit, Card> cbs = MultiMapUtils.newSetValuedHashMap(); this.cards.forEach(card -> cbs.put(card.getSuit(), card)); this.cardsBySuit = MultiMapUtils.unmodifiableMultiValuedMap(cbs); } Apache Collections – Cartesian Product
  • 29. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade this.cards = Card.streamCards() .collect(Collectors.collectingAndThen( Collectors.toCollection(TreeSet::new), Collections::unmodifiableSortedSet)); Apache Collections – Cartesian Product
  • 30. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public class EclipseCollectionsDeckOfCards { private ImmutableSortedSet<Card> cards; private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit; public EclipseCollectionsDeckOfCards() { this.cards = SortedSets.immutable.with( Card.streamCards() .toArray(Card[]::new)); this.cardsBySuit = this.cards.groupBy(Card::getSuit); } Eclipse Collections – Cartesian Product
  • 31. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade this.cards = SortedSets.immutable.with( Card.streamCards() .toArray(Card[]::new)); Eclipse Collections – Cartesian Product
  • 32. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public class GoogleGuavaDeckOfCards { private ImmutableSortedSet<Card> cards; private ImmutableSetMultimap<Suit, Card> cardsBySuit; public GoogleGuavaDeckOfCards() { this.cards = Card.streamCards() .collect(ImmutableSortedSet.toImmutableSortedSet( Comparator.naturalOrder())); ImmutableSetMultimap.Builder<Suit, Card> builder = new ImmutableSetMultimap.Builder<Suit, Card>() .orderValuesBy(Comparator.naturalOrder()); this.cards.forEach(card -> builder.put(card.getSuit(), card)); this.cardsBySuit = builder.build(); } Google Guava – Cartesian Product
  • 33. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade this.cards = Card.streamCards() .collect( ImmutableSortedSet.toImmutableSortedSet( Comparator.naturalOrder())); Google Guava – Cartesian Product
  • 34. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public class JavaSlangDeckOfCards { private SortedSet<Card> cards; private Map<Suit, ? extends SortedSet<Card>> cardsBySuit; public JavaSlangDeckOfCards() { this.cards = Card.streamCards() .collect(TreeSet.collector()); this.cardsBySuit = this.cards.groupBy(Card::getSuit); } Javaslang – Cartesian Product
  • 35. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade this.cards = Card.streamCards() .collect(TreeSet.collector()); Javaslang – Cartesian Product
  • 36. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Problem Statement – Deck of Cards 1. Create Deck of Cards • Store Cards in an “Immutable” SortedSet (Cartesian product of Suit x Rank) • Group the cards by Suit in an “Immutable” SortedSet “Multimap” (Group By) 2. Get the number of cards • Count By Suit returning “Multiset” or “Bag” • Count By Rank returning “Multiset” or “Bag” 3. Deal five hands of five cards each • Return the cards as an “Immutable” List of five Sets of five cards
  • 37. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Performance Test - groupBy 540,396 183,848 231,321 176,412 353,651 - 100,000 200,000 300,000 400,000 500,000 600,000 Scoreops/s Framework groupBy Apache EC Guava Javaslang JDK
  • 38. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public class JDK8DeckOfCards { private SortedSet<Card> cards; private Map<Suit, SortedSet<Card>> cardsBySuit; public JDK8DeckOfCards() { this.cards = Card.streamCards() .collect(Collectors.collectingAndThen( Collectors.toCollection(TreeSet::new), Collections::unmodifiableSortedSet)); this.cardsBySuit = Collections.unmodifiableMap( this.cards.stream().collect(Collectors.groupingBy( Card::getSuit, Collectors.mapping(Function.identity(), Collectors.collectingAndThen( Collectors.toCollection(TreeSet::new), Collections::unmodifiableSortedSet))))); } JDK Collections – Group By
  • 39. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade this.cardsBySuit = Collections.unmodifiableMap( this.cards.stream().collect(Collectors.groupingBy( Card::getSuit, Collectors.mapping(Function.identity(), Collectors.collectingAndThen( Collectors.toCollection(TreeSet::new), Collections::unmodifiableSortedSet))) )); JDK Collections – Group By
  • 40. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public class ApacheCommonsDeckOfCards { private SortedSet<Card> cards; private MultiValuedMap<Suit, Card> cardsBySuit; public ApacheCommonsDeckOfCards() { this.cards = Card.streamCards() .collect(Collectors.collectingAndThen( Collectors.toCollection(TreeSet::new), Collections::unmodifiableSortedSet)); SetValuedMap<Suit, Card> cbs = MultiMapUtils.newSetValuedHashMap(); this.cards.forEach(card -> cbs.put(card.getSuit(), card)); this.cardsBySuit = MultiMapUtils.unmodifiableMultiValuedMap(cbs); } Apache Collections – Group By
  • 41. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade SetValuedMap<Suit, Card> cbs = MultiMapUtils.newSetValuedHashMap(); this.cards.forEach(card -> cbs.put(card.getSuit(), card)); this.cardsBySuit = MultiMapUtils.unmodifiableMultiValuedMap(cbs); Apache Collections – Group By
  • 42. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public class EclipseCollectionsDeckOfCards { private ImmutableSortedSet<Card> cards; private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit; public EclipseCollectionsDeckOfCards() { this.cards = SortedSets.immutable.with( Card.streamCards() .toArray(Card[]::new)); this.cardsBySuit = this.cards.groupBy(Card::getSuit); } Eclipse Collections – Group By
  • 43. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade this.cardsBySuit = this.cards.groupBy(Card::getSuit); Eclipse Collections – Group By
  • 44. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public class GoogleGuavaDeckOfCards { private ImmutableSortedSet<Card> cards; private ImmutableSetMultimap<Suit, Card> cardsBySuit; public GoogleGuavaDeckOfCards() { this.cards = Card.streamCards() .collect(ImmutableSortedSet.toImmutableSortedSet( Comparator.naturalOrder())); ImmutableSetMultimap.Builder<Suit, Card> builder = new ImmutableSetMultimap.Builder<Suit, Card>() .orderValuesBy(Comparator.naturalOrder()); this.cards.forEach(card -> builder.put(card.getSuit(), card)); this.cardsBySuit = builder.build(); } Google Guava – Group By
  • 45. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade ImmutableSetMultimap.Builder<Suit, Card> builder = new ImmutableSetMultimap.Builder<Suit, Card>() .orderValuesBy(Comparator.naturalOrder()); this.cards.forEach(card -> builder.put(card.getSuit(), card)); this.cardsBySuit = builder.build(); Google Guava – Group By
  • 46. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public class JavaSlangDeckOfCards { private SortedSet<Card> cards; private Map<Suit, ? extends SortedSet<Card>> cardsBySuit; public JavaSlangDeckOfCards() { this.cards = Card.streamCards() .collect(TreeSet.collector()); this.cardsBySuit = this.cards.groupBy(Card::getSuit); } Javaslang – Group By
  • 47. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade this.cardsBySuit = this.cards.groupBy(Card::getSuit); Javaslang – Group By
  • 48. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Performance Test - Deck of Cards 102,037 79,343 76,982 56,224 91,017 0 20,000 40,000 60,000 80,000 100,000 120,000Scoreops/s Framework Deck of Cards Apache EC Guava Javaslang JDK 540,396 183,848 231,321 176,412 353,651 - 200,000 400,000 600,000 Scoreops/s Framework groupBy Apache EC Guava Javaslang JDK 185,087 203,660 465,999 127,439 114,634 0 200,000 400,000 600,000 Scoreops/s Framework Cartesian Product Apache EC Guava Javaslang JDK
  • 49. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Problem Statement – Deck of Cards 1. Create Deck of Cards • Store Cards in an “Immutable” SortedSet (Cartesian product of Suit x Rank) • Group the cards by Suit in an “Immutable” SortedSet “Multimap” (Group By) 2. Get the number of cards • Count By Suit returning “Multiset” or “Bag” • Count By Rank returning “Multiset” or “Bag” 3. Deal five hands of five cards each • Return the cards as an “Immutable” List of five Sets of five cards
  • 50. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Performance Test - countsBySuit 706,272 1,096,527 533,728 440,786 724,526 0 200,000 400,000 600,000 800,000 1,000,000 1,200,000 Scoreops/s Framework Apache EC Guava Javaslang JDK
  • 51. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Performance Test - countsByRank 539,252 827,986 444,832 390,134 591,869 0 100,000 200,000 300,000 400,000 500,000 600,000 700,000 800,000 900,000 Scoreops/s Framework Apache EC Guava Javaslang JDK
  • 52. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public Map<Suit, Long> countsBySuit() { return this.cards.stream() .collect(Collectors.groupingBy( Card::getSuit, Collectors.counting())); } public Map<Rank, Long> countsByRank() { return this.cards.stream() .collect(Collectors.groupingBy( Card::getRank, Collectors.counting())); } JDK Collections – Count By
  • 53. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public Bag<Suit> countsBySuit() { return this.cards.stream() .map(Card::getSuit) .collect(Collectors.toCollection( HashBag::new)); } public MultiSet<Rank> countsByRank() { return this.cards.stream() .map(Card::getRank) .collect(Collectors.toCollection( HashMultiSet::new)); } Apache Collections – Count By
  • 54. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public Bag<Suit> countsBySuit() { return this.cards.asLazy() .collect(Card::getSuit) .toBag(); } public Bag<Rank> countsByRank() { return this.cards.asLazy() .collect(Card::getRank) .toBag(); } Eclipse Collections – Count By
  • 55. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public Multiset<Suit> countsBySuit() { return this.cards.stream() .map(Card::getSuit) .collect(Collectors.toCollection( HashMultiset::create)); } public Multiset<Rank> countsByRank() { return this.cards.stream() .map(Card::getRank) .collect(Collectors.toCollection( HashMultiset::create)); } Google Guava – Count By
  • 56. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade public java.util.Map<Suit, Long> countsBySuit() { return this.cards.collect( Collectors.groupingBy( Card::getSuit, Collectors.counting())); } public java.util.Map<Rank, Long> countsByRank() { return this.cards.collect( Collectors.groupingBy( Card::getRank, Collectors.counting())); } Javaslang – Count By
  • 57. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Problem Statement – Deck of Cards 1. Create Deck of Cards • Store Cards in an “Immutable” SortedSet (Cartesian product of Suit x Rank) • Group the cards by Suit in an “Immutable” SortedSet “Multimap” (Group By) 2. Get the number of cards • Count By Suit returning “Multiset” or “Bag” • Count By Rank returning “Multiset” or “Bag” 3. Deal five hands of five cards each • Return the cards as an “Immutable” List of five Sets of five cards
  • 58. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Performance Test – Deal Hands 291,488 502,448 305,673 372,466 300,975 0 100,000 200,000 300,000 400,000 500,000 600,000 Scoreops/s Framework Apache EC Guava Javaslang JDK
  • 59. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade JDK Collections – Deal Hands public List<Set<Card>> dealHands( Deque<Card> shuffled, int hands, int cardsPerHand) { return IntStream.range(0, hands) .mapToObj(i -> this.deal(shuffled, cardsPerHand)) .collect(Collectors.collectingAndThen( Collectors.toList(), Collections::unmodifiableList)); }
  • 60. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Apache Collections – Deal Hands public List<Set<Card>> dealHands( Deque<Card> shuffled, int hands, int cardsPerHand) { return IntStream.range(0, hands) .mapToObj(i -> this.deal(shuffled, cardsPerHand)) .collect(Collectors.collectingAndThen( Collectors.toList(), Collections::unmodifiableList)); }
  • 61. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Eclipse Collections – Deal Hands public ImmutableList<Set<Card>> dealHands( MutableStack<Card> shuffled, int hands, int cardsPerHand) { return IntInterval.oneTo(hands) .collect(i -> this.deal(shuffled, cardsPerHand)); }
  • 62. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Google Guava – Deal Hands public ImmutableList<Set<Card>> dealHands( Deque<Card> shuffled, int hands, int cardsPerHand) { return IntStream.range(0, hands) .mapToObj(i -> this.deal(shuffled, cardsPerHand)) .collect(ImmutableList.toImmutableList()); }
  • 63. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Javaslang – Deal Hands public List<Set<Card>> dealHands( Stack<Card> shuffled, int hands, int cardsPerHand) { List<Set<Card>> list = List.empty(); for (int i = 0; i < hands; i++) { Tuple2<Set<Card>, ? extends Stack<Card>> tuple2 = this.deal(shuffled, cardsPerHand); shuffled = tuple2._2(); list = list.append(tuple2._1()); } return list; }
  • 64. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Feature JDK Apache Guava Eclipse Javaslang 1st, 2nd, 3rd List, Set, Map ✔  ✖ ✔  JDK, EC, JS Multiset / Bag ✖ ✔ ✔ ✔ ✖ GG, EC, AC Multimap ✖ ✔ ✔ ✔ ✔ GG, EC, AC BiMap ✖ ✔ ✔ ✔ ✖ GG, EC, AC Stack ✔  ✖ ✔ ✔ EC, JDK, JS Tree / Trie ✖ ✔ ✖ ✖ ✔ JS, AC Table ✖ ✖ ✔ ✖ ✖ GG Additional Types ✔ ✔ ✔   AC, JDK, GG Immutable? ✖ ✖ ✔ ✔ ✔ JS, EC, GG Primitives?  ✖  ✔ ✖ EC, JDK, GG Fluent API    ✔ ✔ EC, JS, JDK (E), (L), (S), (P)* , ✔, ✔, ✔ , , ✔, ✖ ✖, , ✔, ✖ ✔, ✔, ✔, ✔ ✔, ✔, ✔, ✖ EC, JDK, JS Collection Framework Comparison *(E)ager, (L)azy, (S)erial, (P)arallel – Functional API
  • 65. #CollectionsDevoxxUS @TheDonRaab @leomrlima @NikhilNanivade Links The Collections Compare Project https://github.com/nikhilnanivadekar/CollectionsCompare

Editor's Notes

  • #3: We'd like to have a session for both beginner and seasoned developers that would help them choose which collections framework is better for their projects. While they can look very much alike, there are key differences regarding performance, style of programming and memory impact that are not explicit until you already committed to using one framework over the other.   Our goal is to present common use cases for collections, the frameworks available and how we use them. There should be little slides for use case descriptions and comparison, and actual tests will run from our IDEs. 
  • #4: We'd like to have a session for both beginner and seasoned developers that would help them choose which collections framework is better for their projects. While they can look very much alike, there are key differences regarding performance, style of programming and memory impact that are not explicit until you already committed to using one framework over the other.   Our goal is to present common use cases for collections, the frameworks available and how we use them. There should be little slides for use case descriptions and comparison, and actual tests will run from our IDEs.