javaone 2017 - collections.compare:jdk, eclipse, guava, apache... [con1754]
Post on 28-Jan-2018
196 Views
Preview:
TRANSCRIPT
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Collections.compare(() -> {JDK; Apache; Eclipse; Guava...});
Donald Raab
Leonardo Lima
Nikhil J. Nanivadekar
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Abstract
� Collections are a staple in any programming language: the need to collect, sort or iterate over values is needed by nearly all developers.
The Java language introduced the Collections framework long ago and that's what many (incredibly not all!) developers learn when they start programming. It has plenty to offer, but many find it lacking: the amount of collection libraries as active opensource projects demonstrate the need for something else.
If we were to search to find a holistic comparison of famous collection libraries, there is not much literature available. The talk is poised to fill this gap. In this session, we will explore the most common collections (pun intended!) frameworks, what they have to offer and what you should consider for your next project.
We will also show common programmer use cases, how each library handles them and the impact on memory, processing power and ease of use/coding.
After this session, you will be able to choose the right bag for your tricks!
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Agenda1. Brief introduction of who we are (2 min)
2. A bit of history about the Java Util Collections framework (6 min), with a timeline of Java releases and what was introduced in its collection
3. Show the gaps in use cases from that timeline (6 min)
4. Introduce a timeline with other collection frameworks (6 min, 2 min per framework: Apache, Eclipse, Google)
5. Comparison table with use case / packages diagram (5+ min)
6. Examples of said use cases in IDE (10 min)
7. Actual tests with speed and memory use per solution (rest of time)
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
About the Speakers
�Donald Raab
• Managing Director at BNY Mellon• Based in Jersey City, New Jersey• Creator of Eclipse Collections• Member of JSR 335 Expert Group (Lambdas/Streams 4 Java)• Presenter at Devoxx US, JavaOne, EclipseCon, JVMLS, GIDS
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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• V2COM’s Representative at JCP Executive Committee
[about.me/leomrlima]
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
�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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
java.util.Collections
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Java 21998
• Interfaces• Collection• List• Set• Map• List• SortedMap
Java 52005
• Generics• For-each loop• Interfaces
• Iterable• Queue• ConcurrentMap• BlockingQueue
Java 62006
•Interfaces•NavigableSet•NavigableMap•Deque•BlockingDeque•ConcurrentNavigableMap
Java 72011
• Interfaces• TransferQueu
e
Java 82014
• 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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
!java.util.Collections?
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
!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!)
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Collection Frameworks Timeline
Java 21998
• JakartaCollections 1.0• 2001
• Apache Collections 3.0 (AC)• 2004
Java 62006
• Google Collections 1.0• Dec. 2009
Java 72011
• Google Guava 10.0• Sept. 2011
• GS Collections 1.0• Jan. 2012
• AC 4.0• Nov. 2013
Java 82014
• 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 92017
• 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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Collections.compare();
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Use Case – Deck of Cards
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Problem Statement – Deck of Cards1. 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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Problem Statement – Deck of Cards1. 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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Performance Test - Deck of Cards
166,268179,728
147,495
179,159165,415
0
20,000
40,000
60,000
80,000
100,000
120,000
140,000
160,000
180,000
200,000Sc
ore
ops/
s
Framework
Deck of Cards
Apache EC Guava JDK Vavr
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Performance Notes• JDK and Apache do not have Immutable
Collections• Guava’s ImmutableList is backed by an
ImmutableList• Eclipse Collection’s ImmutableList is backed
by an array• JavaSlang’s TreeSet is backed by a
RedBlackTree
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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;
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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;
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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;
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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;
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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;
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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;
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Problem Statement – Deck of Cards1. 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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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)));}
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Eclipse Collections – Cartesian Product
public static LazyIterable<Card> lazyCards() {
return Sets.cartesianProduct(EnumSet.allOf(Rank.class),EnumSet.allOf(Suit.class),Card::new);
}
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Performance Test – ImmutableList
207,258
225,904
187,521 190,509180,838
0
50,000
100,000
150,000
200,000
250,000Sc
ore
ops/
s
Framework
ImmutableList
Apache EC Guava JDK Vavr
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Memory Test – ImmutableList
2888
2776 2776
2896
2824
2700
2720
2740
2760
2780
2800
2820
2840
2860
2880
2900
2920
Framework
Byt
es
ImmutableList
Apache EC Guava JDK Vavr
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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”
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
this.cards = Collections.unmodifiableList(
Card.streamCards().sorted().collect(Collectors.toList()));
JDK Collections – “ImmutableList”
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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”
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
this.cards = ListUtils.unmodifiableList(
Card.streamCards().sorted().collect(Collectors.toList()));
Apache Collections – “ImmutableList”
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
this.cards = Card.lazyCards()
.toSortedList()
.toImmutable();
Eclipse Collections – ImmutableList
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
this.cards = Card.streamCards()
.sorted()
.collect(ImmutableList.toImmutableList());
Google Guava – ImmutableList
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
this.cards = Card.streamCards()
.sorted()
.collect(List.collector());
Vavr – ImmutableList
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Performance Notes• Guava’s ImmutableList Collector uses an
ArrayBasedBuilder for adding elements• The final build step creates the sorts the array and
constructs the ImmutableList• Eclipse Collections creates a TreeSet from
the array of cards• The TreeSet is converted to an array via toArray
for final storage
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Problem Statement – Deck of Cards1. 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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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 Sc
ore
ops/
s
Framework
groupBy
Apache EC Guava JDK Vavr
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Memory Test – groupBy
3336
29523136
3336
4208
0
500
1000
1500
2000
2500
3000
3500
4000
4500
Framework
Byt
es
groupBy
Apache EC Guava JDK Vavr
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
ListValuedMap<Suit, Card> cbs = MultiMapUtils.newListValuedHashMap();
this.cards.forEach(card -> cbs.put(card.getSuit(), card));
this.cardsBySuit = MultiMapUtils.unmodifiableMultiValuedMap(cbs);
Apache Collections – Group By
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
this.cardsBySuit = this.cards.groupBy(Card::getSuit);
Eclipse Collections – Group By
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Google Guava – Group Bypublic 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);
}
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
this.cardsBySuit = Multimaps.index(this.cards, Card::getSuit);
Google Guava – Group By
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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);
}
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
this.cardsBySuit = this.cards.groupBy(Card::getSuit);
Vavr – Group By
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Performance Test - Deck of Cards
207,258225,904
187,521 190,509 180,838
ImmutableList
832,841
617,693 459,074
1,123,706
695,402
groupBy
166,268179,728
147,495
179,159165,415
Deck of Cards
Apache EC Guava JDK Vavr
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Memory Test – Deck of Cards
36083216
34003720
5480
0
1000
2000
3000
4000
5000
6000
Framework
Byt
es
Deck of Cards
Apache EC Guava JDK Vavr
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Problem Statement – Deck of Cards1. 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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Performance Test - countsBySuit
1,302,792
1,797,399
1,488,6931,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,000Sc
ore
ops/
s
Framework
countsBySuit
Apache EC Guava JDK Vavr
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Memory Test - countsBySuit
672
408
704
600 600
0
100
200
300
400
500
600
700
800
Framework
Byt
es
countsBySuit
Apache EC Guava JDK Vavr
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Performance Test - countsByRank
889,401
1,339,267
1,136,795
1,289,5201,208,456
0
200,000
400,000
600,000
800,000
1,000,000
1,200,000
1,400,000
1,600,000Sc
ore
ops/
s
Framework
countsByRank
Apache EC Guava JDK Vavr
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Memory Test – countsByRank
1816
1136
1848
1600 1600
0
200
400
600
800
1000
1200
1400
1600
1800
2000
Framework
Byt
es
countsByRank
Apache EC Guava JDK Vavr
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
public Bag<Suit> countsBySuit() {return this.cards.countBy(Card::getSuit);
}
public Bag<Rank> countsByRank() {return this.cards.countBy(Card::getRank);
}
Eclipse Collections – Count By
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Problem Statement – Deck of Cards1. 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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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,000Sc
ore
ops/
s
Framework
Deal
Apache EC Guava JDK Vavr
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Memory Test – Deal Hands
3528
2440
3488 3536
3120
0
500
1000
1500
2000
2500
3000
3500
4000
Framework
Byt
es
Deal
Apache EC Guava JDK Vavr
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
JDK Collections – Deal Handspublic 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()));
}
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Apache Collections – Deal Handspublic 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()));
}
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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));}
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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());}
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Vavr – Deal Handspublic 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;
}
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
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
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Links� The Collections Compare Project� https://github.com/nikhilnanivadekar/Coll
ectionsCompare
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
? & !
Coll
ecti
ons.
comp
are(
()->
{…})
@TheDonRaab @leomrlima @NikhilNanivade#JavaOne
Thanks!
top related