SlideShare a Scribd company logo
Collections.compare(() -> {
JDK; Apache; Eclipse; Guava...});
Nikhil J. Nanivadekar
#CollectionsCompare #GIDS17 @NikhilNanivade
Agenda
1. Introduction
2. History of Java util collections framework
3. Gaps in use cases from the timeline
4. Timeline with other collection frameworks
5. Use case, domain diagrams
6. Deep dive in use case
7. Memory characteristics
#CollectionsCompare #GIDS17 @NikhilNanivade
Authors
• Donald Raab (@TheDonRaab)
• Leonardo Lima (@leomrlima)
• Nikhil J. Nanivadekar (@NikhilNanivade)
#CollectionsCompare #GIDS17 @NikhilNanivade
Speaker
Nikhil J. Nanivadekar
– Mechanical Engineer
– Software developer
– Vice President, Technology at Goldman Sachs
– From Pune, Maharashtra currently in Salt Lake City,
Utah
java.util Collections
#CollectionsCompare #GIDS17 @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
#CollectionsCompare #GIDS17 @NikhilNanivade
Java Collections Frameworks
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.util Collections?
#CollectionsCompare #GIDS17 @NikhilNanivade
!java.util Collections
• We’re considering 4 collection frameworks, in
alphabetical order:
• Apache Commons Collection
– version 4.1
• Eclipse Collections (Formerly GS Collections)
– version 8.1.0
• Google Guava
– version 21.0
• Javaslang (now called Vavr)
– version 2.1.0-alpha
#CollectionsCompare #GIDS17 @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
Collections.compare();
#CollectionsCompare #GIDS17 @NikhilNanivade
Use Case – Deck of Cards
The Collections Compare Project: https://github.com/nikhilnanivadekar/CollectionsCompare
#CollectionsCompare #GIDS17 @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
#CollectionsCompare #GIDS17 @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
#CollectionsCompare #GIDS17 @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
#CollectionsCompare #GIDS17 @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
#CollectionsCompare #GIDS17 @NikhilNanivade
A Deck of Cards – Only the Types
public class JDK8DeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, SortedSet<Card>> cardsBySuit;
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;
#CollectionsCompare #GIDS17 @NikhilNanivade
A Deck of Cards – Only the Types
public class JDK8DeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, SortedSet<Card>> cardsBySuit;
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;
#CollectionsCompare #GIDS17 @NikhilNanivade
A Deck of Cards – Only the Types
public class JDK8DeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, SortedSet<Card>> cardsBySuit;
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;
#CollectionsCompare #GIDS17 @NikhilNanivade
A Deck of Cards – Only the Types
public class JDK8DeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, SortedSet<Card>> cardsBySuit;
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;
#CollectionsCompare #GIDS17 @NikhilNanivade
A Deck of Cards – Only the Types
public class JDK8DeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, SortedSet<Card>> cardsBySuit;
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;
#CollectionsCompare #GIDS17 @NikhilNanivade
A Deck of Cards – Only the Types
public class JDK8DeckOfCards {
private SortedSet<Card> cards;
private Map<Suit, SortedSet<Card>> cardsBySuit;
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;
#CollectionsCompare #GIDS17 @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
#CollectionsCompare #GIDS17 @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)));
}
#CollectionsCompare #GIDS17 @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
#CollectionsCompare #GIDS17 @NikhilNanivade
JDK Collections – Cartesian Product
public class JDK8DeckOfCards {
private SortedSet<Card> cards;
public JDK8DeckOfCards() {
this.cards = Card.streamCards()
.collect(Collectors.collectingAndThen(
Collectors.toCollection(TreeSet::new),
Collections::unmodifiableSortedSet));
}
#CollectionsCompare #GIDS17 @NikhilNanivade
Apache Collections – Cartesian Product
public class ApacheCommonsDeckOfCards {
private SortedSet<Card> cards;
public ApacheCommonsDeckOfCards() {
this.cards = Card.streamCards()
.collect(Collectors.collectingAndThen(
Collectors.toCollection(TreeSet::new),
Collections::unmodifiableSortedSet));
}
#CollectionsCompare #GIDS17 @NikhilNanivade
Eclipse Collections – Cartesian Product
public class EclipseCollectionsDeckOfCards {
private ImmutableSortedSet<Card> cards;
public EclipseCollectionsDeckOfCards() {
this.cards = SortedSets.immutable.with(
Card.streamCards()
.toArray(Card[]::new));
}
#CollectionsCompare #GIDS17 @NikhilNanivade
Google Guava – Cartesian Product
public class GoogleGuavaDeckOfCards {
private ImmutableSortedSet<Card> cards;
public GoogleGuavaDeckOfCards() {
this.cards = Card.streamCards()
.collect(ImmutableSortedSet
.toImmutableSortedSet(
Comparator.naturalOrder()));
}
#CollectionsCompare #GIDS17 @NikhilNanivade
Javaslang – Cartesian Product
public class JavaSlangDeckOfCards {
private SortedSet<Card> cards;
public JavaSlangDeckOfCards() {
this.cards = Card.streamCards()
.collect(TreeSet.collector());
}
#CollectionsCompare #GIDS17 @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
#CollectionsCompare #GIDS17 @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
#CollectionsCompare #GIDS17 @NikhilNanivade
JDK Collections – Group By
public class JDK8DeckOfCards {
private Map<Suit, SortedSet<Card>> cardsBySuit;
public JDK8DeckOfCards() {
this.cardsBySuit =
Collections.unmodifiableMap(
this.cards.stream()
.collect(Collectors.groupingBy(
Card::getSuit,
Collectors.mapping(
Function.identity(),
Collectors.collectingAndThen(
Collectors.toCollection(TreeSet::new),
Collections::unmodifiableSortedSet)))));
}
#CollectionsCompare #GIDS17 @NikhilNanivade
Apache Collections – Group By
public class ApacheCommonsDeckOfCards {
private MultiValuedMap<Suit, Card> cardsBySuit;
public ApacheCommonsDeckOfCards() {
SetValuedMap<Suit, Card> cbs =
MultiMapUtils.newSetValuedHashMap();
this.cards.forEach(card ->
cbs.put(card.getSuit(), card));
this.cardsBySuit =
MultiMapUtils.unmodifiableMultiValuedMap(cbs);
}
#CollectionsCompare #GIDS17 @NikhilNanivade
Eclipse Collections – Group By
public class EclipseCollectionsDeckOfCards {
private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit;
public EclipseCollectionsDeckOfCards() {
this.cardsBySuit = this.cards.groupBy(Card::getSuit);
}
#CollectionsCompare #GIDS17 @NikhilNanivade
Google Guava – Group By
public class GoogleGuavaDeckOfCards {
private ImmutableSetMultimap<Suit, Card> cardsBySuit;
public GoogleGuavaDeckOfCards() {
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();
}
#CollectionsCompare #GIDS17 @NikhilNanivade
Javaslang – Group By
public class JavaSlangDeckOfCards {
private Map<Suit, ? extends SortedSet<Card>> cardsBySuit;
public JavaSlangDeckOfCards() {
this.cardsBySuit = this.cards.groupBy(Card::getSuit);
}
#CollectionsCompare #GIDS17 @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
540,396
183,848231,321176,412
353,651
-
500,000
1,000,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
#CollectionsCompare #GIDS17 @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
#CollectionsCompare #GIDS17 @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
#CollectionsCompare #GIDS17 @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
#CollectionsCompare #GIDS17 @NikhilNanivade
JDK Collections – Count By
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()));
}
#CollectionsCompare #GIDS17 @NikhilNanivade
Apache Collections – Count By
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));
}
#CollectionsCompare #GIDS17 @NikhilNanivade
Eclipse Collections – Count By
public Bag<Suit> countsBySuit() {
return this.cards.asLazy()
.collect(Card::getSuit)
.toBag();
}
public Bag<Rank> countsByRank() {
return this.cards.asLazy()
.collect(Card::getRank)
.toBag();
}
#CollectionsCompare #GIDS17 @NikhilNanivade
Google Guava – Count By
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));
}
#CollectionsCompare #GIDS17 @NikhilNanivade
Javaslang – Count By
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()));
}
#CollectionsCompare #GIDS17 @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
#CollectionsCompare #GIDS17 @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
#CollectionsCompare #GIDS17 @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));
}
#CollectionsCompare #GIDS17 @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));
}
#CollectionsCompare #GIDS17 @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));
}
#CollectionsCompare #GIDS17 @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());
}
#CollectionsCompare #GIDS17 @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;
}
Memory Benchmarks
#CollectionsCompare #GIDS17 @NikhilNanivade
Memory Benchmarks
• ObjectExplorer, by Dimitris Andrew
• Open Source under Apache License 2.0
• Measure Reported –
– Memory (Kb) vs Size
– Memory (Kb) vs List, Set, Map with 1,000,000 elements
• Smaller the better
Sources
– GitHub:
https://github.com/DimitrisAndreou/memory-measurer
– Found from StackOverflow:
http://stackoverflow.com/a/9368930/5182052
#CollectionsCompare #GIDS17 @NikhilNanivade
List<Integer>
#CollectionsCompare #GIDS17 @NikhilNanivade
List<Integer>
#CollectionsCompare #GIDS17 @NikhilNanivade
List<String>
#CollectionsCompare #GIDS17 @NikhilNanivade
List<String>
#CollectionsCompare #GIDS17 @NikhilNanivade
Set<Integer>
#CollectionsCompare #GIDS17 @NikhilNanivade
Set<Integer>
#CollectionsCompare #GIDS17 @NikhilNanivade
Set<String>
#CollectionsCompare #GIDS17 @NikhilNanivade
Set<String>
#CollectionsCompare #GIDS17 @NikhilNanivade
Map<Integer, Integer>
#CollectionsCompare #GIDS17 @NikhilNanivade
Map<Integer, Integer>
#CollectionsCompare #GIDS17 @NikhilNanivade
Map<String, String>
#CollectionsCompare #GIDS17 @NikhilNanivade
Map<String, String>
Summary
#CollectionsCompare #GIDS17 @NikhilNanivade
Link
• The Collections Compare Project
https://github.com/nikhilnanivadekar/CollectionsCompare
#CollectionsCompare #GIDS17 @NikhilNanivade
Collection Framework Comparison
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
Thanks!
The Collections Compare Project
https://github.com/nikhilnanivadekar/CollectionsCompare

More Related Content

PPTX
Collections.compare(JDK, Eclipse, Guava, Apache...);
PPTX
Collections.compare(() -> JDK; Apache; Eclipse, Guava...});
PPTX
Collections.compare(JDK, Eclipse, Guava, Apache...); DevoxxUS 2017
PDF
JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]
PDF
So S.O.L.I.D Fu - Designing Better Code
PDF
Find your data - using GraphDB capabilities in XPages applications - ICS.UG 2016
PDF
Apache Spark for Library Developers with Erik Erlandson and William Benton
PDF
Visage Android Hands-on Lab (OSCON)
Collections.compare(JDK, Eclipse, Guava, Apache...);
Collections.compare(() -> JDK; Apache; Eclipse, Guava...});
Collections.compare(JDK, Eclipse, Guava, Apache...); DevoxxUS 2017
JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]
So S.O.L.I.D Fu - Designing Better Code
Find your data - using GraphDB capabilities in XPages applications - ICS.UG 2016
Apache Spark for Library Developers with Erik Erlandson and William Benton
Visage Android Hands-on Lab (OSCON)

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

PPTX
10 Strategies for Developing Reliable Jakarta EE & MicroProfile Applications ...
PPTX
jCardSim - development platform for Java Card Applications
PDF
The cost of learning - advantage of mixer2
PDF
JavaCro 2014 Scala and Java EE 7 Development Experiences
PDF
JavaCro'14 - Scala and Java EE 7 Development Experiences – Peter Pilgrim
PPTX
Preparing for java 9 modules upload
PDF
DIとトレイとによるAndroid開発の効率化
PPTX
Apache spark core
PDF
Scala Frustrations
PPTX
Modules in Java? Finally! (OpenJDK 9 Jigsaw, JSR376)
PDF
Module, AMD, RequireJS
PDF
[Pgday.Seoul 2018] 이기종 DB에서 PostgreSQL로의 Migration을 위한 DB2PG
PPT
Backbone js-slides
PDF
Using Backbone.js with Drupal 7 and 8
PDF
[DSC 2016] 系列活動:李泳泉 / 星火燎原 - Spark 機器學習初探
PPTX
Packing for the Web with Webpack
PDF
"Xapi-lang For declarative code generation" By James Nelson
PDF
Webpack Encore - Asset Management for the rest of us
PPTX
Php on the Web and Desktop
PDF
S313431 JPA 2.0 Overview
10 Strategies for Developing Reliable Jakarta EE & MicroProfile Applications ...
jCardSim - development platform for Java Card Applications
The cost of learning - advantage of mixer2
JavaCro 2014 Scala and Java EE 7 Development Experiences
JavaCro'14 - Scala and Java EE 7 Development Experiences – Peter Pilgrim
Preparing for java 9 modules upload
DIとトレイとによるAndroid開発の効率化
Apache spark core
Scala Frustrations
Modules in Java? Finally! (OpenJDK 9 Jigsaw, JSR376)
Module, AMD, RequireJS
[Pgday.Seoul 2018] 이기종 DB에서 PostgreSQL로의 Migration을 위한 DB2PG
Backbone js-slides
Using Backbone.js with Drupal 7 and 8
[DSC 2016] 系列活動:李泳泉 / 星火燎原 - Spark 機器學習初探
Packing for the Web with Webpack
"Xapi-lang For declarative code generation" By James Nelson
Webpack Encore - Asset Management for the rest of us
Php on the Web and Desktop
S313431 JPA 2.0 Overview
Ad

Recently uploaded (20)

PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
Machine learning based COVID-19 study performance prediction
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PPTX
Spectroscopy.pptx food analysis technology
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
A comparative analysis of optical character recognition models for extracting...
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
cuic standard and advanced reporting.pdf
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
“AI and Expert System Decision Support & Business Intelligence Systems”
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Encapsulation_ Review paper, used for researhc scholars
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
NewMind AI Weekly Chronicles - August'25-Week II
Advanced methodologies resolving dimensionality complications for autism neur...
MIND Revenue Release Quarter 2 2025 Press Release
Machine learning based COVID-19 study performance prediction
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Dropbox Q2 2025 Financial Results & Investor Presentation
Spectroscopy.pptx food analysis technology
The Rise and Fall of 3GPP – Time for a Sabbatical?
20250228 LYD VKU AI Blended-Learning.pptx
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Reach Out and Touch Someone: Haptics and Empathic Computing
A comparative analysis of optical character recognition models for extracting...
Chapter 3 Spatial Domain Image Processing.pdf
cuic standard and advanced reporting.pdf
Per capita expenditure prediction using model stacking based on satellite ima...
Ad

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

  • 1. Collections.compare(() -> { JDK; Apache; Eclipse; Guava...}); Nikhil J. Nanivadekar
  • 2. #CollectionsCompare #GIDS17 @NikhilNanivade Agenda 1. Introduction 2. History of Java util collections framework 3. Gaps in use cases from the timeline 4. Timeline with other collection frameworks 5. Use case, domain diagrams 6. Deep dive in use case 7. Memory characteristics
  • 3. #CollectionsCompare #GIDS17 @NikhilNanivade Authors • Donald Raab (@TheDonRaab) • Leonardo Lima (@leomrlima) • Nikhil J. Nanivadekar (@NikhilNanivade)
  • 4. #CollectionsCompare #GIDS17 @NikhilNanivade Speaker Nikhil J. Nanivadekar – Mechanical Engineer – Software developer – Vice President, Technology at Goldman Sachs – From Pune, Maharashtra currently in Salt Lake City, Utah
  • 6. #CollectionsCompare #GIDS17 @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. #CollectionsCompare #GIDS17 @NikhilNanivade Java Collections Frameworks 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
  • 9. #CollectionsCompare #GIDS17 @NikhilNanivade !java.util Collections • We’re considering 4 collection frameworks, in alphabetical order: • Apache Commons Collection – version 4.1 • Eclipse Collections (Formerly GS Collections) – version 8.1.0 • Google Guava – version 21.0 • Javaslang (now called Vavr) – version 2.1.0-alpha
  • 10. #CollectionsCompare #GIDS17 @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
  • 12. #CollectionsCompare #GIDS17 @NikhilNanivade Use Case – Deck of Cards The Collections Compare Project: https://github.com/nikhilnanivadekar/CollectionsCompare
  • 13. #CollectionsCompare #GIDS17 @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. #CollectionsCompare #GIDS17 @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. #CollectionsCompare #GIDS17 @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. #CollectionsCompare #GIDS17 @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. #CollectionsCompare #GIDS17 @NikhilNanivade A Deck of Cards – Only the Types public class JDK8DeckOfCards { private SortedSet<Card> cards; private Map<Suit, SortedSet<Card>> cardsBySuit; 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. #CollectionsCompare #GIDS17 @NikhilNanivade A Deck of Cards – Only the Types public class JDK8DeckOfCards { private SortedSet<Card> cards; private Map<Suit, SortedSet<Card>> cardsBySuit; 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. #CollectionsCompare #GIDS17 @NikhilNanivade A Deck of Cards – Only the Types public class JDK8DeckOfCards { private SortedSet<Card> cards; private Map<Suit, SortedSet<Card>> cardsBySuit; 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. #CollectionsCompare #GIDS17 @NikhilNanivade A Deck of Cards – Only the Types public class JDK8DeckOfCards { private SortedSet<Card> cards; private Map<Suit, SortedSet<Card>> cardsBySuit; 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. #CollectionsCompare #GIDS17 @NikhilNanivade A Deck of Cards – Only the Types public class JDK8DeckOfCards { private SortedSet<Card> cards; private Map<Suit, SortedSet<Card>> cardsBySuit; 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. #CollectionsCompare #GIDS17 @NikhilNanivade A Deck of Cards – Only the Types public class JDK8DeckOfCards { private SortedSet<Card> cards; private Map<Suit, SortedSet<Card>> cardsBySuit; 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. #CollectionsCompare #GIDS17 @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. #CollectionsCompare #GIDS17 @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. #CollectionsCompare #GIDS17 @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. #CollectionsCompare #GIDS17 @NikhilNanivade JDK Collections – Cartesian Product public class JDK8DeckOfCards { private SortedSet<Card> cards; public JDK8DeckOfCards() { this.cards = Card.streamCards() .collect(Collectors.collectingAndThen( Collectors.toCollection(TreeSet::new), Collections::unmodifiableSortedSet)); }
  • 27. #CollectionsCompare #GIDS17 @NikhilNanivade Apache Collections – Cartesian Product public class ApacheCommonsDeckOfCards { private SortedSet<Card> cards; public ApacheCommonsDeckOfCards() { this.cards = Card.streamCards() .collect(Collectors.collectingAndThen( Collectors.toCollection(TreeSet::new), Collections::unmodifiableSortedSet)); }
  • 28. #CollectionsCompare #GIDS17 @NikhilNanivade Eclipse Collections – Cartesian Product public class EclipseCollectionsDeckOfCards { private ImmutableSortedSet<Card> cards; public EclipseCollectionsDeckOfCards() { this.cards = SortedSets.immutable.with( Card.streamCards() .toArray(Card[]::new)); }
  • 29. #CollectionsCompare #GIDS17 @NikhilNanivade Google Guava – Cartesian Product public class GoogleGuavaDeckOfCards { private ImmutableSortedSet<Card> cards; public GoogleGuavaDeckOfCards() { this.cards = Card.streamCards() .collect(ImmutableSortedSet .toImmutableSortedSet( Comparator.naturalOrder())); }
  • 30. #CollectionsCompare #GIDS17 @NikhilNanivade Javaslang – Cartesian Product public class JavaSlangDeckOfCards { private SortedSet<Card> cards; public JavaSlangDeckOfCards() { this.cards = Card.streamCards() .collect(TreeSet.collector()); }
  • 31. #CollectionsCompare #GIDS17 @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
  • 32. #CollectionsCompare #GIDS17 @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
  • 33. #CollectionsCompare #GIDS17 @NikhilNanivade JDK Collections – Group By public class JDK8DeckOfCards { private Map<Suit, SortedSet<Card>> cardsBySuit; public JDK8DeckOfCards() { this.cardsBySuit = Collections.unmodifiableMap( this.cards.stream() .collect(Collectors.groupingBy( Card::getSuit, Collectors.mapping( Function.identity(), Collectors.collectingAndThen( Collectors.toCollection(TreeSet::new), Collections::unmodifiableSortedSet))))); }
  • 34. #CollectionsCompare #GIDS17 @NikhilNanivade Apache Collections – Group By public class ApacheCommonsDeckOfCards { private MultiValuedMap<Suit, Card> cardsBySuit; public ApacheCommonsDeckOfCards() { SetValuedMap<Suit, Card> cbs = MultiMapUtils.newSetValuedHashMap(); this.cards.forEach(card -> cbs.put(card.getSuit(), card)); this.cardsBySuit = MultiMapUtils.unmodifiableMultiValuedMap(cbs); }
  • 35. #CollectionsCompare #GIDS17 @NikhilNanivade Eclipse Collections – Group By public class EclipseCollectionsDeckOfCards { private ImmutableSortedSetMultimap<Suit, Card> cardsBySuit; public EclipseCollectionsDeckOfCards() { this.cardsBySuit = this.cards.groupBy(Card::getSuit); }
  • 36. #CollectionsCompare #GIDS17 @NikhilNanivade Google Guava – Group By public class GoogleGuavaDeckOfCards { private ImmutableSetMultimap<Suit, Card> cardsBySuit; public GoogleGuavaDeckOfCards() { 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(); }
  • 37. #CollectionsCompare #GIDS17 @NikhilNanivade Javaslang – Group By public class JavaSlangDeckOfCards { private Map<Suit, ? extends SortedSet<Card>> cardsBySuit; public JavaSlangDeckOfCards() { this.cardsBySuit = this.cards.groupBy(Card::getSuit); }
  • 38. #CollectionsCompare #GIDS17 @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 540,396 183,848231,321176,412 353,651 - 500,000 1,000,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
  • 39. #CollectionsCompare #GIDS17 @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
  • 40. #CollectionsCompare #GIDS17 @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
  • 41. #CollectionsCompare #GIDS17 @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
  • 42. #CollectionsCompare #GIDS17 @NikhilNanivade JDK Collections – Count By 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())); }
  • 43. #CollectionsCompare #GIDS17 @NikhilNanivade Apache Collections – Count By 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)); }
  • 44. #CollectionsCompare #GIDS17 @NikhilNanivade Eclipse Collections – Count By public Bag<Suit> countsBySuit() { return this.cards.asLazy() .collect(Card::getSuit) .toBag(); } public Bag<Rank> countsByRank() { return this.cards.asLazy() .collect(Card::getRank) .toBag(); }
  • 45. #CollectionsCompare #GIDS17 @NikhilNanivade Google Guava – Count By 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)); }
  • 46. #CollectionsCompare #GIDS17 @NikhilNanivade Javaslang – Count By 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())); }
  • 47. #CollectionsCompare #GIDS17 @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
  • 48. #CollectionsCompare #GIDS17 @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
  • 49. #CollectionsCompare #GIDS17 @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)); }
  • 50. #CollectionsCompare #GIDS17 @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)); }
  • 51. #CollectionsCompare #GIDS17 @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)); }
  • 52. #CollectionsCompare #GIDS17 @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()); }
  • 53. #CollectionsCompare #GIDS17 @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; }
  • 55. #CollectionsCompare #GIDS17 @NikhilNanivade Memory Benchmarks • ObjectExplorer, by Dimitris Andrew • Open Source under Apache License 2.0 • Measure Reported – – Memory (Kb) vs Size – Memory (Kb) vs List, Set, Map with 1,000,000 elements • Smaller the better Sources – GitHub: https://github.com/DimitrisAndreou/memory-measurer – Found from StackOverflow: http://stackoverflow.com/a/9368930/5182052
  • 69. #CollectionsCompare #GIDS17 @NikhilNanivade Link • The Collections Compare Project https://github.com/nikhilnanivadekar/CollectionsCompare
  • 70. #CollectionsCompare #GIDS17 @NikhilNanivade Collection Framework Comparison 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
  • 71. Thanks! The Collections Compare Project https://github.com/nikhilnanivadekar/CollectionsCompare