JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

79
Collections.compare(() -> {…}) @TheDonRaab @leomrlima @NikhilNanivade #JavaOne Collections.compare(() -> { JDK; Apache; Eclipse; Guava...}); Donald Raab Leonardo Lima Nikhil J. Nanivadekar

Transcript of JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

Page 1: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

Coll

ecti

ons.

comp

are(

()->

{…})

@TheDonRaab @leomrlima @NikhilNanivade#JavaOne

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

Donald Raab

Leonardo Lima

Nikhil J. Nanivadekar

Page 2: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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!

Page 3: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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)

Page 4: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 5: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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]

Page 6: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 7: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

Coll

ecti

ons.

comp

are(

()->

{…})

@TheDonRaab @leomrlima @NikhilNanivade#JavaOne

java.util.Collections

Page 8: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 9: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 10: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

Coll

ecti

ons.

comp

are(

()->

{…})

@TheDonRaab @leomrlima @NikhilNanivade#JavaOne

!java.util.Collections?

Page 11: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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!)

Page 12: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 13: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

Coll

ecti

ons.

comp

are(

()->

{…})

@TheDonRaab @leomrlima @NikhilNanivade#JavaOne

Collections.compare();

Page 14: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

Coll

ecti

ons.

comp

are(

()->

{…})

@TheDonRaab @leomrlima @NikhilNanivade#JavaOne

Use Case – Deck of Cards

Page 15: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 16: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 17: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 18: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 19: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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;

Page 20: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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;

Page 21: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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;

Page 22: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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;

Page 23: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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;

Page 24: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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;

Page 25: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 26: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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)));}

Page 27: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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);

}

Page 28: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 29: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 30: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 31: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 32: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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”

Page 33: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

Coll

ecti

ons.

comp

are(

()->

{…})

@TheDonRaab @leomrlima @NikhilNanivade#JavaOne

this.cards = Collections.unmodifiableList(

Card.streamCards().sorted().collect(Collectors.toList()));

JDK Collections – “ImmutableList”

Page 34: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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”

Page 35: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

Coll

ecti

ons.

comp

are(

()->

{…})

@TheDonRaab @leomrlima @NikhilNanivade#JavaOne

this.cards = ListUtils.unmodifiableList(

Card.streamCards().sorted().collect(Collectors.toList()));

Apache Collections – “ImmutableList”

Page 36: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 37: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

Coll

ecti

ons.

comp

are(

()->

{…})

@TheDonRaab @leomrlima @NikhilNanivade#JavaOne

this.cards = Card.lazyCards()

.toSortedList()

.toImmutable();

Eclipse Collections – ImmutableList

Page 38: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 39: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

Coll

ecti

ons.

comp

are(

()->

{…})

@TheDonRaab @leomrlima @NikhilNanivade#JavaOne

this.cards = Card.streamCards()

.sorted()

.collect(ImmutableList.toImmutableList());

Google Guava – ImmutableList

Page 40: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 41: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

Coll

ecti

ons.

comp

are(

()->

{…})

@TheDonRaab @leomrlima @NikhilNanivade#JavaOne

this.cards = Card.streamCards()

.sorted()

.collect(List.collector());

Vavr – ImmutableList

Page 42: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 43: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 44: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 45: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 46: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 47: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 48: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 49: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 50: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 51: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

Coll

ecti

ons.

comp

are(

()->

{…})

@TheDonRaab @leomrlima @NikhilNanivade#JavaOne

this.cardsBySuit = this.cards.groupBy(Card::getSuit);

Eclipse Collections – Group By

Page 52: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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);

}

Page 53: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

Coll

ecti

ons.

comp

are(

()->

{…})

@TheDonRaab @leomrlima @NikhilNanivade#JavaOne

this.cardsBySuit = Multimaps.index(this.cards, Card::getSuit);

Google Guava – Group By

Page 54: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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);

}

Page 55: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

Coll

ecti

ons.

comp

are(

()->

{…})

@TheDonRaab @leomrlima @NikhilNanivade#JavaOne

this.cardsBySuit = this.cards.groupBy(Card::getSuit);

Vavr – Group By

Page 56: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 57: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 58: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 59: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 60: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 61: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 62: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 63: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 64: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 65: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 66: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 67: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 68: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 69: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 70: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 71: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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()));

}

Page 72: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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()));

}

Page 73: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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));}

Page 74: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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());}

Page 75: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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;

}

Page 76: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

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

Page 77: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

Coll

ecti

ons.

comp

are(

()->

{…})

@TheDonRaab @leomrlima @NikhilNanivade#JavaOne

Links� The Collections Compare Project� https://github.com/nikhilnanivadekar/Coll

ectionsCompare

Page 78: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

Coll

ecti

ons.

comp

are(

()->

{…})

@TheDonRaab @leomrlima @NikhilNanivade#JavaOne

? & !

Page 79: JavaOne 2017 - Collections.compare:JDK, Eclipse, Guava, Apache... [CON1754]

Coll

ecti

ons.

comp

are(

()->

{…})

@TheDonRaab @leomrlima @NikhilNanivade#JavaOne

Thanks!