Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Collections.compare(() -> {
JDK; Apache; Eclipse; Guava...});
Donald Raab
Leonardo Lima
Nikhil J. Nanivadekar
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
java.util.Collections
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
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
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Java 2
1998
• Interfaces
• Collection
• List
• Set
• Map
• List
• SortedMap
Java 5
2005
• Generics
• For-each loop
• Interfaces
• Iterable
• Queue
• ConcurrentMa
p
• BlockingQueu
e
Java 6
2006
•Interfaces
•NavigableSet
•NavigableMap
•Deque
•BlockingDeque
•ConcurrentNavigableM
ap
Java 7
2011
• Interfaces
• TransferQue
ue
Java 8
2014
• Lambdas
• Method Refs
• Default Methods
• Interfaces
• BaseStream
• Stream
• IntStream
• LongStream
• DoubleStream
• Collector
• Spliterator
• PrimitiveIterator
Java 9
2017
• JPMS
• Collection
Factory
methods
• New Stream
APIs
• Improved
Javadoc
• Private
interface
methods
Java Collections Framework
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
!java.util.Collections?
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
!java.util Collections
 We’re comparing 4 other collection
frameworks, and JDK 8 Collections. In
alphabetical order:
 Apache Commons Collections (v 4.1)
 Eclipse Collections (fka GS Collections, v 9.0)
 Google Guava’s Collections (v23)
 Vavr’s Collections (fka Javaslang, v0.9)
 (links are to their user guide/documentation!)
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Collection Frameworks Timeline
Java 2
1998
• Jakarta
Collections 1.0
• 2001
• Apache
Collections 3.0
(AC)
• 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
• AC 4.0
• Nov. 2013
Java 8
2014
• Javaslang 1.0
• Mar. 2014
• AC 4.1
• Nov. 2015
• Eclipse Collections
7.0 (EC)
• Jan. 2016
• EC 8.0 (Java 8)
• Sept. 2016
• Guava 20.0
• Oct. 2016
• Javaslang 2.1a
• Nov. 2016
Java 9
2017
• Guava 21.0
(Java 8)
• Jan. 2017
• EC 8.1
• Mar. 2017
• Vavr 0.9
• May 2017
• Guava 22.0
• May 2017
• EC 8.2
• Jun 2017
• Guava 23.0
• Aug 2017
• EC 9.0
• Sep 2017
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Latest Versions
Framework Latest Version Released
Apache Collections 4.1 November 2015
Eclipse Collections 9.1 December 2017
Google Guava 24.0 February 2018
Java Streams JDK 9 September 2017
Vavr 0.9.2 November 2017
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Collections.compare();
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Use Case – Deck of Cards
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Problem Statement – Deck of
Cards
1. Create Deck of Cards
• Store Cards in an “ImmutableList”
• (Cartesian product of Suit x Rank)
• Group the cards by Suit in an “ImmutableListMultimap”
• (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 “ImmutableList” of five Sets of five
cards
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Problem Statement – Deck of
Cards
1. Create Deck of Cards
• Store Cards in an “ImmutableList”
• (Cartesian product of Suit x Rank)
• Group the cards by Suit in an “ImmutableListMultimap”
• (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 “ImmutableList” of five Sets of five
cards
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
public class JDK8DeckOfCards {
private List<Card> cards;
private Map<Suit, List<Card>> cardsBySuit;
A Deck of Cards – Only the Types
public class ApacheCommonsDeckOfCards {
private List<Card> cards;
private MultiValuedMap<Suit, Card> cardsBySuit;
public class EclipseCollectionsDeckOfCards {
private ImmutableList<Card> cards;
private ImmutableListMultimap<Suit, Card> cardsBySuit;
public class GoogleGuavaDeckOfCards {
private ImmutableList<Card> cards;
private ImmutableListMultimap<Suit, Card> cardsBySuit;
public class VavrDeckOfCards {
private List<Card> cards;
private Map<Suit, ? extends List<Card>> cardsBySuit;
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
public class JDK8DeckOfCards {
private List<Card> cards;
private Map<Suit, List<Card>> cardsBySuit;
A Deck of Cards – Only the Types
public class ApacheCommonsDeckOfCards {
private List<Card> cards;
private MultiValuedMap<Suit, Card> cardsBySuit;
public class EclipseCollectionsDeckOfCards {
private ImmutableList<Card> cards;
private ImmutableListMultimap<Suit, Card> cardsBySuit;
public class GoogleGuavaDeckOfCards {
private ImmutableList<Card> cards;
private ImmutableListMultimap<Suit, Card> cardsBySuit;
public class VavrDeckOfCards {
private List<Card> cards;
private Map<Suit, ? extends List<Card>> cardsBySuit;
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
public class JDK8DeckOfCards {
private List<Card> cards;
private Map<Suit, List<Card>> cardsBySuit;
A Deck of Cards – Only the Types
public class ApacheCommonsDeckOfCards {
private List<Card> cards;
private MultiValuedMap<Suit, Card> cardsBySuit;
public class EclipseCollectionsDeckOfCards {
private ImmutableList<Card> cards;
private ImmutableListMultimap<Suit, Card> cardsBySuit;
public class GoogleGuavaDeckOfCards {
private ImmutableList<Card> cards;
private ImmutableListMultimap<Suit, Card> cardsBySuit;
public class VavrDeckOfCards {
private List<Card> cards;
private Map<Suit, ? extends List<Card>> cardsBySuit;
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
public class JDK8DeckOfCards {
private List<Card> cards;
private Map<Suit, List<Card>> cardsBySuit;
A Deck of Cards – Only the Types
public class ApacheCommonsDeckOfCards {
private List<Card> cards;
private MultiValuedMap<Suit, Card> cardsBySuit;
public class EclipseCollectionsDeckOfCards {
private ImmutableList<Card> cards;
private ImmutableListMultimap<Suit, Card> cardsBySuit;
public class GoogleGuavaDeckOfCards {
private ImmutableList<Card> cards;
private ImmutableListMultimap<Suit, Card> cardsBySuit;
public class VavrDeckOfCards {
private List<Card> cards;
private Map<Suit, ? extends List<Card>> cardsBySuit;
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
public class JDK8DeckOfCards {
private List<Card> cards;
private Map<Suit, List<Card>> cardsBySuit;
A Deck of Cards – Only the Types
public class ApacheCommonsDeckOfCards {
private List<Card> cards;
private MultiValuedMap<Suit, Card> cardsBySuit;
public class EclipseCollectionsDeckOfCards {
private ImmutableList<Card> cards;
private ImmutableListMultimap<Suit, Card> cardsBySuit;
public class GoogleGuavaDeckOfCards {
private ImmutableList<Card> cards;
private ImmutableListMultimap<Suit, Card> cardsBySuit;
public class VavrDeckOfCards {
private List<Card> cards;
private Map<Suit, ? extends List<Card>> cardsBySuit;
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
public class JDK8DeckOfCards {
private List<Card> cards;
private Map<Suit, List<Card>> cardsBySuit;
A Deck of Cards – Only the Types
public class ApacheCommonsDeckOfCards {
private List<Card> cards;
private MultiValuedMap<Suit, Card> cardsBySuit;
public class EclipseCollectionsDeckOfCards {
private ImmutableList<Card> cards;
private ImmutableListMultimap<Suit, Card> cardsBySuit;
public class GoogleGuavaDeckOfCards {
private ImmutableList<Card> cards;
private ImmutableListMultimap<Suit, Card> cardsBySuit;
public class VavrDeckOfCards {
private List<Card> cards;
private Map<Suit, ? extends List<Card>> cardsBySuit;
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Problem Statement – Deck of
Cards
1. Create Deck of Cards
• Store Cards in an “ImmutableList”
• (Cartesian product of Suit x Rank)
• Group the cards by Suit in an “ImmutableListMultimap”
• (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 “ImmutableList” of five Sets of five
cards
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Shared Code – Cartesian
Productpublic 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)));
}
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Eclipse Collections – Cartesian Product
public static LazyIterable<Card> lazyCards()
{
return Sets.cartesianProduct(
EnumSet.allOf(Rank.class),
EnumSet.allOf(Suit.class),
Card::new);
}
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
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, 3 forks
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Memory Tests
• ObjectSizeCalculator.getObjectSize()
• Internal class in Nashorn
• Java 8
• Smaller numbers are better
• We test the size of the data structures created in
each code example
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Performance Test – ImmutableList
207,258
225,904
187,521 190,509
180,838
0
50,000
100,000
150,000
200,000
250,000
Scoreops/s
Framework
ImmutableList
Apache EC Guava JDK Vavr
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Memory Test – ImmutableList
2888
2776 2776
2896
2824
2700
2720
2740
2760
2780
2800
2820
2840
2860
2880
2900
2920
Framework
Bytes
ImmutableList
Apache EC Guava JDK Vavr
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
public class JDK8DeckOfCards {
private List<Card> cards;
private Map<Suit, List<Card>> cardsBySuit;
public JDK8DeckOfCards() {
this.cards = Collections.unmodifiableList(
Card.streamCards().sorted().collect(Collectors.toList()));
this.cardsBySuit =
this.cards.stream().collect(Collectors.collectingAndThen(
Collectors.groupingBy(
Card::getSuit,
Collectors.mapping(Function.identity(),
Collectors.collectingAndThen(
Collectors.toList(),
Collections::unmodifiableList))),
Collections::unmodifiableMap));
}
JDK Collections – “ImmutableList”
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
this.cards =
Collections.unmodifiableList(
Card.streamCards()
.sorted()
.collect(Collectors.toList()));
JDK Collections – “ImmutableList”
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
public class ApacheCommonsDeckOfCards {
private List<Card> cards;
private MultiValuedMap<Suit, Card> cardsBySuit;
public ApacheCommonsDeckOfCards() {
this.cards = ListUtils.unmodifiableList(
Card.streamCards().sorted().collect(Collectors.toList()));
ListValuedMap<Suit, Card> cbs = MultiMapUtils.newListValuedHashMap();
this.cards.forEach(card -> cbs.put(card.getSuit(), card));
this.cardsBySuit = MultiMapUtils.unmodifiableMultiValuedMap(cbs);
}
Apache Collections – “ImmutableList”
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
this.cards =
ListUtils.unmodifiableList(
Card.streamCards()
.sorted()
.collect(Collectors.toList()));
Apache Collections – “ImmutableList”
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
public class EclipseCollectionsDeckOfCards {
private ImmutableList<Card> cards;
private ImmutableListMultimap<Suit, Card> cardsBySuit;
public EclipseCollectionsDeckOfCards() {
this.cards = Card.lazyCards().toSortedList().toImmutable();
this.cardsBySuit = this.cards.groupBy(Card::getSuit);
}
Eclipse Collections – ImmutableList
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
this.cards =
Card.lazyCards()
.toSortedList()
.toImmutable();
Eclipse Collections – ImmutableList
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
public class GoogleGuavaDeckOfCards {
private ImmutableList<Card> cards;
private ImmutableListMultimap<Suit, Card> cardsBySuit;
public GoogleGuavaDeckOfCards() {
this.cards =
Card.streamCards().sorted().collect(ImmutableList.toImmutableList());
this.cardsBySuit = Multimaps.index(this.cards, Card::getSuit);
}
Google Guava – ImmutableList
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
this.cards =
Card.streamCards()
.sorted()
.collect(ImmutableList.toImmutableList());
Google Guava – ImmutableList
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
public class VavrDeckOfCards {
private List<Card> cards;
private Map<Suit, ? extends List<Card>> cardsBySuit;
public VavrDeckOfCards() {
this.cards = Card.streamCards().sorted().collect(List.collector());
this.cardsBySuit = this.cards.groupBy(Card::getSuit);
}
Vavr – ImmutableList
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
this.cards =
Card.streamCards()
.sorted()
.collect(List.collector());
Vavr – ImmutableList
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Problem Statement – Deck of
Cards
1. Create Deck of Cards
• Store Cards in an “ImmutableList”
• (Cartesian product of Suit x Rank)
• Group the cards by Suit in an “ImmutableListMultimap”
• (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 “ImmutableList” of five Sets of five
cards
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Performance Test - groupBy
832,841
617,693
459,074
1,123,706
695,402
-
200,000
400,000
600,000
800,000
1,000,000
1,200,000
Scoreops/s
Framework
groupBy
Apache EC Guava JDK Vavr
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Memory Test – groupBy
3336
2952
3136
3336
4208
0
500
1000
1500
2000
2500
3000
3500
4000
4500
Framework
Bytes
groupBy
Apache EC Guava JDK Vavr
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
public class JDK8DeckOfCards {
private List<Card> cards;
private Map<Suit, List<Card>> cardsBySuit;
public JDK8DeckOfCards() {
this.cards = Collections.unmodifiableList(
Card.streamCards().sorted().collect(Collectors.toList()));
this.cardsBySuit =
this.cards.stream().collect(Collectors.collectingAndThen(
Collectors.groupingBy(
Card::getSuit,
Collectors.mapping(Function.identity(),
Collectors.collectingAndThen(
Collectors.toList(),
Collections::unmodifiableList))),
Collections::unmodifiableMap));
}
JDK Collections – Group By
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
this.cardsBySuit =
this.cards.stream().collect(Collectors.collectingAndThen(
Collectors.groupingBy(
Card::getSuit,
Collectors.mapping(Function.identity(),
Collectors.collectingAndThen(
Collectors.toList(),
Collections::unmodifiableList))),
Collections::unmodifiableMap));
JDK Collections – Group By
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
public class ApacheCommonsDeckOfCards {
private List<Card> cards;
private MultiValuedMap<Suit, Card> cardsBySuit;
public ApacheCommonsDeckOfCards() {
this.cards = ListUtils.unmodifiableList(
Card.streamCards().sorted().collect(Collectors.toList()));
ListValuedMap<Suit, Card> cbs = MultiMapUtils.newListValuedHashMap();
this.cards.forEach(card -> cbs.put(card.getSuit(), card));
this.cardsBySuit = MultiMapUtils.unmodifiableMultiValuedMap(cbs);
}
Apache Collections – Group By
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
ListValuedMap<Suit, Card> cbs =
MultiMapUtils.newListValuedHashMap();
this.cards.forEach(
card -> cbs.put(card.getSuit(), card));
this.cardsBySuit =
MultiMapUtils.unmodifiableMultiValuedMap(cbs);
Apache Collections – Group By
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
public class EclipseCollectionsDeckOfCards {
private ImmutableList<Card> cards;
private ImmutableListMultimap<Suit, Card> cardsBySuit;
public EclipseCollectionsDeckOfCards() {
this.cards = Card.lazyCards().toSortedList().toImmutable();
this.cardsBySuit = this.cards.groupBy(Card::getSuit);
}
Eclipse Collections – Group By
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
this.cardsBySuit =
this.cards.groupBy(Card::getSuit);
Eclipse Collections – Group By
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Google Guava – Group By
public class GoogleGuavaDeckOfCards {
private ImmutableList<Card> cards;
private ImmutableListMultimap<Suit, Card> cardsBySuit;
public GoogleGuavaDeckOfCards() {
this.cards =
Card.streamCards().sorted().collect(ImmutableList.toImmutableList());
this.cardsBySuit = Multimaps.index(this.cards, Card::getSuit);
}
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
this.cardsBySuit =
Multimaps.index(this.cards, Card::getSuit);
Google Guava – Group By
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Vavr – Group By
public class VavrDeckOfCards {
private List<Card> cards;
private Map<Suit, ? extends List<Card>> cardsBySuit;
public VavrDeckOfCards() {
this.cards = Card.streamCards().sorted().collect(List.collector());
this.cardsBySuit = this.cards.groupBy(Card::getSuit);
}
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
this.cardsBySuit =
this.cards.groupBy(Card::getSuit);
Vavr – Group By
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Performance Test - Deck of Cards
207,258
225,904
187,521 190,509 180,838
ImmutableList
832,841
617,693
459,074
1,123,706
695,402
groupBy
166,268
179,728
147,495
179,159
165,415
Deck of Cards
Apache EC Guava JDK Vavr
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Memory Test – Deck of Cards
3608
3216
3400
3720
5480
0
1000
2000
3000
4000
5000
6000
Framework
Bytes
Deck of Cards
Apache EC Guava JDK Vavr
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Problem Statement – Deck of
Cards
1. Create Deck of Cards
• Store Cards in an “ImmutableList”
• (Cartesian product of Suit x Rank)
• Group the cards by Suit in an “ImmutableListMultimap”
• (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 “ImmutableList” of five Sets of five
cards
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Performance Test - countsBySuit
1,302,792
1,797,399
1,488,693
1,553,906
1,432,836
0
200,000
400,000
600,000
800,000
1,000,000
1,200,000
1,400,000
1,600,000
1,800,000
2,000,000
Scoreops/s
Framework
countsBySuit
Apache EC Guava JDK Vavr
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Memory Test - countsBySuit
672
408
704
600 600
0
100
200
300
400
500
600
700
800
Framework
Bytes
countsBySuit
Apache EC Guava JDK Vavr
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Performance Test - countsByRank
889,401
1,339,267
1,136,795
1,289,520
1,208,456
0
200,000
400,000
600,000
800,000
1,000,000
1,200,000
1,400,000
1,600,000
Scoreops/s
Framework
countsByRank
Apache EC Guava JDK Vavr
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Memory Test – countsByRank
1816
1136
1848
1600 1600
0
200
400
600
800
1000
1200
1400
1600
1800
2000
Framework
Bytes
countsByRank
Apache EC Guava JDK Vavr
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
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
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
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
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
public Bag<Suit> countsBySuit()
{
return this.cards.countBy(Card::getSuit);
}
public Bag<Rank> countsByRank()
{
return this.cards.countBy(Card::getRank);
}
Eclipse Collections – Count By
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
public Multiset<Suit> countsBySuit() {
return this.cards.stream()
.collect(Multisets.toMultiset(
Card::getSuit, e -> 1, HashMultiset::create));
}
public Multiset<Rank> countsByRank() {
return this.cards.stream()
.collect(Multisets.toMultiset(
Card::getRank, e -> 1, HashMultiset::create));
}
Google Guava – Count By
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
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()));
}
Vavr – Count By
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Problem Statement – Deck of
Cards
1. Create Deck of Cards
• Store Cards in an “ImmutableList”
• (Cartesian product of Suit x Rank)
• Group the cards by Suit in an “ImmutableListMultimap”
• (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 “ImmutableList” of five Sets of five
cards
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Performance Test – Deal Hands
935,213
1,320,811
935,860 945,125
716,883
0
200,000
400,000
600,000
800,000
1,000,000
1,200,000
1,400,000
Scoreops/s
Framework
Deal
Apache EC Guava JDK Vavr
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Memory Test – Deal Hands
3528
2440
3488 3536
3120
0
500
1000
1500
2000
2500
3000
3500
4000
Framework
Bytes
Deal
Apache EC Guava JDK Vavr
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
JDK Collections – Deal Hands
public List<Set<Card>> dealHands(
Deque<Card> shuffled,
int hands,
int cardsPerHand)
{
return Collections.unmodifiableList(
IntStream.range(0, hands)
.mapToObj(i -> this.deal(shuffled, cardsPerHand))
.collect(Collectors.toList()));
}
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Apache Collections – Deal Hands
public List<Set<Card>> dealHands(
Deque<Card> shuffled,
int hands,
int cardsPerHand)
{
return ListUtils.unmodifiableList(
IntStream.range(0, hands)
.mapToObj(i -> this.deal(shuffled, cardsPerHand))
.collect(Collectors.toList()));
}
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
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));
}
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
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());
}
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Vavr – Deal Hands
public List<Set<Card>> dealHands(
List<Card> shuffled,
int hands,
int cardsPerHand)
{
List<Set<Card>> list = List.empty();
for (int i = 0; i < hands; i++) {
Tuple2<Set<Card>, List<Card>> tuple2 =
this.deal(shuffled, cardsPerHand);
shuffled = tuple2._2();
list = list.append(tuple2._1());
}
return list;
}
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Feature JDK Apache Guava Eclipse Vavr 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
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Links
 The Collections Compare Project
https://github.com/nikhilnanivadekar/CollectionsCom
pare
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
? & !
Collections.compare(()->{…})
@TheDonRaab @leomrlima @NikhilNanivade#eurojug
Thanks!

Collections.compare(() -> JDK; Apache; Eclipse, Guava...});

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.