Sitemap
Javarevisited

A humble place to learn Java and Programming better.

Happy Holidays!

--

It’s time for some Java Reindeer games.

A Festival of lights in New York

This blog is going to be mostly code. I am going to demonstrate some Eclipse Collections and Java Stream APIs, with a holiday twist. I’ll start by implementing a Reindeer Enum in Java with some help from .

public enum Reindeer
{
Dasher, Dancer, Prancer, Vixen, Comet, Cupid, Donner, Blitzen,
Rudolph;

public static ImmutableList<Reindeer> all()
{
return theMostFamousReindeerOfAll()
.newWithAll(theOtherReindeer()
.flatCollect(Reindeer::toList));
}

private static ImmutableList<Twin<Reindeer>> theOtherReindeer()
{
return Lists.immutable.with(
Dasher.and(Dancer),
Prancer.and(Vixen),
Comet.and(Cupid),
Donner.and(Blitzen));
}

private static ImmutableList<Reindeer> theMostFamousReindeerOfAll()
{
return Lists.immutable.with(Reindeer.Rudolph);
}

private static ImmutableList<Reindeer> toList(Twin<Reindeer> twin)
{
return Lists.immutable.with(twin.getOne(), twin.getTwo());
}

public Twin<Reindeer> and(Reindeer other)
{
return Tuples.twin(this, other);
}

public int nameLength()
{
return this.name().length();
}

public Character firstLetterOfName()
{
return Character.valueOf(this.name().charAt(0));
}
}

First, I create an of Reindeer with Rudolph at the front in the method named all. I create an ImmutableList of pairs of all of the other reindeer, based on their usual order in the popular song. I use the type , which is a that has the same type for both items. Finally, I used the method to flatten all of the pairs of Reindeer into a single list which is appended to the ImmutableList with Rudolph using the method.

Now I will implement some tests for the Reindeer name games.

/**
* Create a comma separated String of the Reindeer names.
*/
@Test
public void reindeerNameGame1()
{
String expectedNames = "Rudolph, " +
"Dasher, Dancer, " +
"Prancer, Vixen, " +
"Comet, Cupid, " +
"Donner, Blitzen";

Assert.assertEquals(
expectedNames,
Reindeer.all().makeString(", "));

Assert.assertEquals(
expectedNames,
String.join(", ",
Reindeer.all()
.asLazy()
.collect(Reindeer::name)));

Assert.assertEquals(
expectedNames,
Reindeer.all()
.stream()
.map(Reindeer::name)
.collect(Collectors.joining(", ")));
}

In this test, I show three different ways a comma separated String of the reindeer names can be created. First, I use from Eclipse Collections. The method does not require the object to be a CharSequence. It uses the toString implementation of the Object.

Next, I use which was added in Java 8. This method takes an Iterable of CharSequence, which I create using a with .

Finally, I use a with the ImmutableList returned from all and then map each Reindeer to its name, and collect them all into a String using Collectors.joining. All three approaches have the exact same result.

/**
* Count the Reindeer names based on their size.
*/
@Test
public void reindeerNameGame2()
{
IntBag nameCounts =
Reindeer.all()
.asLazy()
.collectInt(Reindeer::nameLength).toBag();

IntBag nameCountsFromIntStream =
IntBags.mutable.withAll(
Reindeer.all()
.stream()
.mapToInt(Reindeer::nameLength));

Assert.assertEquals(nameCounts, nameCountsFromIntStream);
Assert.assertEquals(3, nameCounts.occurrencesOf(5));
Assert.assertEquals(3, nameCounts.occurrencesOf(6));
Assert.assertEquals(3, nameCounts.occurrencesOf(7));

Bag<Integer> nameCountsBy =
Reindeer.all().countBy(Reindeer::nameLength);

Assert.assertEquals(3, nameCountsBy.occurrencesOf(5));
Assert.assertEquals(3, nameCountsBy.occurrencesOf(6));
Assert.assertEquals(3, nameCountsBy.occurrencesOf(7));

Map<Integer, Long> streamNameCounts =
Reindeer.all()
.stream()
.collect(Collectors.groupingBy(
Reindeer::nameLength,
Collectors.counting()));

Assert.assertEquals(new Long(3), streamNameCounts.get(5));
Assert.assertEquals(new Long(3), streamNameCounts.get(6));
Assert.assertEquals(new Long(3), streamNameCounts.get(7));
}

In this test, I show four different ways to count the names of the Reindeer by their length. First, I create an , by collecting all of the name lengths for the Reindeer using and then converting the result .

In the second case, I create an IntStream from the Reindeer by mapping their name lengths to an int using mapToInt. I use the method to create an IntBag from an IntStream.

This method became available in Eclipse Collections 9.0 (Look at Item #3 for a comparison to previous versions). The third solution is the simplest. I use the method which is available on types that extend in Eclipse Collections.

Finally, I use Stream with Collectors.groupingBy and which results in a Map of Integer to Long.

/**
* Group Reindeer by the first letter of their names.
*/
@Test
public void reindeerNameGame3()
{
Multimap<Character, Reindeer> multimap =
Reindeer.all().groupBy(Reindeer::firstLetterOfName);

Map<Character, List<Reindeer>> mapOfLists =
Reindeer.all()
.stream()
.collect(Collectors.groupingBy(
Reindeer::firstLetterOfName));

Assert.assertEquals("Dasher, Dancer, Donner",
multimap.get('D').makeString(", "));
Assert.assertEquals("Comet, Cupid",
multimap.get('C').makeString(", "));
Assert.assertEquals(multimap.get('D'), mapOfLists.get('D'));
Assert.assertEquals(multimap.get('C'), mapOfLists.get('C'));
}

In this test, I illustrate two ways to group Reindeer by the first letter of their last name. First, I use the method available directly on ImmutableList, which returns a .

In the second example, I use the stream method on and collect method on Stream with the groupingBy Collector on the utility class.

I hope you enjoyed joining in these reindeer games. I explored a bunch of and APIs in these three examples that may be useful in your own Java code.

Have a Happy Holiday and Happy New Year!

is open for . If you like the library, you can let us know by starring it on GitHub.

Javarevisited
Javarevisited

Published in Javarevisited

A humble place to learn Java and Programming better.

Donald Raab
Donald Raab

Written by Donald Raab

Java Champion. Creator of the Eclipse Collections OSS Java library (). Inspired by Smalltalk. Opinions are my own.

No responses yet