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

PDF
JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]
PDF
JavaOne 2017 - JNoSQL: The Definitive Solution for Java and NoSQL Database [C...
PDF
JavaOne 2017 - Choosing a NoSQL API and Database to Avoid Tombstones and Drag...
PDF
Scala, Akka, and Play: An Introduction on Heroku
PDF
Build Cloud Applications with Akka and Heroku
PDF
Scala in a wild enterprise
PDF
Scala Days NYC 2016
PDF
Solid And Sustainable Development in Scala
JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]
JavaOne 2017 - JNoSQL: The Definitive Solution for Java and NoSQL Database [C...
JavaOne 2017 - Choosing a NoSQL API and Database to Avoid Tombstones and Drag...
Scala, Akka, and Play: An Introduction on Heroku
Build Cloud Applications with Akka and Heroku
Scala in a wild enterprise
Scala Days NYC 2016
Solid And Sustainable Development in Scala

What's hot (20)

PDF
Scala profiling
PDF
BOF2644 Developing Java EE 7 Scala apps
PDF
JavaCro 2014 Scala and Java EE 7 Development Experiences
PDF
QCon 2015 Scala for the Enterprise: Get FuNkEd Up on the JVM
PPTX
Scala elegant and exotic part 1
PPTX
Responsive Facets with Apache Solr
PDF
Scala @ TechMeetup Edinburgh
PDF
Scarab: SAT-based Constraint Programming System in Scala / Scala上で実現された制約プログラ...
PPTX
An Introduction to Scala
PPTX
Scala in practice
PDF
The Evolution of Scala / Scala進化論
PDF
Advanced Production Debugging
PPTX
Akka Actor presentation
PDF
pull requests I sent to scala/scala (ny-scala 2019)
PDF
ITFT - Java Coding
PPTX
Introduction to Scala
PPTX
Building a Unified Data Pipline in Spark / Apache Sparkを用いたBig Dataパイプラインの統一
PPTX
Java 201 Intro to Test Driven Development in Java
PDF
Introduction to Scala : Clueda
PDF
A Scala tutorial
Scala profiling
BOF2644 Developing Java EE 7 Scala apps
JavaCro 2014 Scala and Java EE 7 Development Experiences
QCon 2015 Scala for the Enterprise: Get FuNkEd Up on the JVM
Scala elegant and exotic part 1
Responsive Facets with Apache Solr
Scala @ TechMeetup Edinburgh
Scarab: SAT-based Constraint Programming System in Scala / Scala上で実現された制約プログラ...
An Introduction to Scala
Scala in practice
The Evolution of Scala / Scala進化論
Advanced Production Debugging
Akka Actor presentation
pull requests I sent to scala/scala (ny-scala 2019)
ITFT - Java Coding
Introduction to Scala
Building a Unified Data Pipline in Spark / Apache Sparkを用いたBig Dataパイプラインの統一
Java 201 Intro to Test Driven Development in Java
Introduction to Scala : Clueda
A Scala tutorial
Ad

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

PPTX
Collections.compare(() -> JDK; Apache; Eclipse, Guava...});
PPTX
Collections.compare(JDK, Eclipse, Guava, Apache...); GIDS 2017
PPTX
Java Hands-On Workshop
PDF
Collectn framework
PDF
Collectn framework copy
PDF
JAVA PROGRAMMING - The Collections Framework
PDF
Scala Collections : Java 8 on Steroids
PPTX
Java collections
PPTX
Java collections
PDF
Google Guava for cleaner code
PDF
Java collections
PPTX
Java 103
PPTX
Java Unit 2 (Part 2)
PDF
The Sincerest Form of Flattery
PPTX
Collections
PPTX
Java.util
PPTX
LJ_JAVA_FS_Collection.pptx
PDF
Collections forceawakens
PDF
Google guava overview
PPT
DataStructureLists Stacks Queues and more
Collections.compare(() -> JDK; Apache; Eclipse, Guava...});
Collections.compare(JDK, Eclipse, Guava, Apache...); GIDS 2017
Java Hands-On Workshop
Collectn framework
Collectn framework copy
JAVA PROGRAMMING - The Collections Framework
Scala Collections : Java 8 on Steroids
Java collections
Java collections
Google Guava for cleaner code
Java collections
Java 103
Java Unit 2 (Part 2)
The Sincerest Form of Flattery
Collections
Java.util
LJ_JAVA_FS_Collection.pptx
Collections forceawakens
Google guava overview
DataStructureLists Stacks Queues and more
Ad

More from Leonardo De Moura Rocha Lima (10)

PPTX
Top 9 mistakes to avoid when developing with NoSQL
PPTX
JSR363 - Devoxx US
PPTX
IoT Security: Cases and Methods
PPTX
The First IoT JSR: Units of Measurement JSR-363 [BOF5981]
PPTX
Using Java and Standards for Fast IoT Development [CON5513]
PPTX
IoT Security: Cases and Methods [CON5446]
PPTX
Secure IoT with Blockchain: Fad or Reality? [BOF5490]
PPTX
Building a Reliable Remote Communication Device with Java ME8 [CON2285]
PDF
A internet das coisas e o futuro - Java ME 8 e adiante!
Top 9 mistakes to avoid when developing with NoSQL
JSR363 - Devoxx US
IoT Security: Cases and Methods
The First IoT JSR: Units of Measurement JSR-363 [BOF5981]
Using Java and Standards for Fast IoT Development [CON5513]
IoT Security: Cases and Methods [CON5446]
Secure IoT with Blockchain: Fad or Reality? [BOF5490]
Building a Reliable Remote Communication Device with Java ME8 [CON2285]
A internet das coisas e o futuro - Java ME 8 e adiante!

Recently uploaded (20)

PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Approach and Philosophy of On baking technology
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Unlocking AI with Model Context Protocol (MCP)
PPTX
A Presentation on Artificial Intelligence
PDF
Network Security Unit 5.pdf for BCA BBA.
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PPTX
Programs and apps: productivity, graphics, security and other tools
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Encapsulation theory and applications.pdf
DOCX
The AUB Centre for AI in Media Proposal.docx
PPTX
Machine Learning_overview_presentation.pptx
PPTX
sap open course for s4hana steps from ECC to s4
PDF
Machine learning based COVID-19 study performance prediction
PDF
cuic standard and advanced reporting.pdf
MIND Revenue Release Quarter 2 2025 Press Release
The Rise and Fall of 3GPP – Time for a Sabbatical?
Reach Out and Touch Someone: Haptics and Empathic Computing
MYSQL Presentation for SQL database connectivity
Approach and Philosophy of On baking technology
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Unlocking AI with Model Context Protocol (MCP)
A Presentation on Artificial Intelligence
Network Security Unit 5.pdf for BCA BBA.
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Programs and apps: productivity, graphics, security and other tools
“AI and Expert System Decision Support & Business Intelligence Systems”
Dropbox Q2 2025 Financial Results & Investor Presentation
Encapsulation_ Review paper, used for researhc scholars
Encapsulation theory and applications.pdf
The AUB Centre for AI in Media Proposal.docx
Machine Learning_overview_presentation.pptx
sap open course for s4hana steps from ECC to s4
Machine learning based COVID-19 study performance prediction
cuic standard and advanced reporting.pdf

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

  • 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.