javaone 2017 - collections.compare:jdk, eclipse, guava, apache... [con1754]

Post on 28-Jan-2018

196 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

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