# The 4am Jamestown-Scotland ferry and other optimization strategies

Jan 3, 2018 · 13 min read

## Eager vs. Lazy — Understanding how they work

`@Testpublic void eagerVsLazy(){    long eagerSum = Lists.mutable.with(1, 2, 3, 4, 5)            .tap(i -> System.out.println("eager select: " + i))            .select(i -> i % 2 == 0)            .tap(i -> System.out.println("eager collect: " + i))            .collectInt(i -> i * 2)            .tap(i -> System.out.println("eager sum: " + i))            .sum();    System.out.println(eagerSum);    long lazySum = Lists.mutable.with(1, 2, 3, 4, 5)            .asLazy()            .tap(i -> System.out.println("lazy select: " + i))            .select(i -> i % 2 == 0)            .tap(i -> System.out.println("lazy collect: " + i))            .collectInt(i -> i * 2)            .tap(i -> System.out.println("lazy sum: " + i))            .sum();    System.out.println(lazySum);    Assert.assertEquals(eagerSum, lazySum);}`
`eager select: 1eager select: 2eager select: 3eager select: 4eager select: 5eager collect: 2eager collect: 4eager sum: 4eager sum: 812lazy select: 1lazy select: 2lazy collect: 2lazy sum: 4lazy select: 3lazy select: 4lazy collect: 4lazy sum: 8lazy select: 512`
`@Testpublic void stream(){    int streamSum = Lists.mutable.with(1, 2, 3, 4, 5)            .stream()            .peek(i -> System.out.println("stream filter: "+ i))            .filter(i -> i % 2 == 0)            .peek(i -> System.out.println("stream map: "+ i))            .mapToInt(i -> i * 2)            .peek(i -> System.out.println("stream sum: "+ i))            .sum();    System.out.println(streamSum);}`
`stream filter: 1stream filter: 2stream map: 2stream sum: 4stream filter: 3stream filter: 4stream map: 4stream sum: 8stream filter: 512`
`@Testpublic void parallel(){    long parallelSum = Lists.mutable.with(1, 2, 3, 4, 5)            .asParallel(Executors.newWorkStealingPool(), 1)            .select(i -> {                System.out.println("parallel select: " + i);                return i % 2 == 0;            })            .collect(i -> {                System.out.println("parallel collect: " + i);                return i * 2;            })            .sumOfInt(i -> {                System.out.println("parallel sum: " + i);                return i;            });    System.out.println(parallelSum);}Run 1:parallel select: 2parallel select: 1parallel select: 4parallel collect: 4parallel select: 3sum: 8parallel select: 5parallel collect: 2sum: 412Run 2:parallel select: 1parallel select: 3parallel select: 2parallel select: 5parallel select: 4parallel collect: 2parallel collect: 4parallel sum: 4parallel sum: 812Run 3:parallel select: 4parallel select: 2parallel collect: 2parallel select: 5parallel select: 3parallel select: 1parallel sum: 4parallel collect: 4parallel sum: 812`
`@Testpublic void parallelStream(){    int streamSum = Interval.oneTo(5).toList()            .parallelStream()            .peek(i -> System.out.println("stream filter: "+ i))            .filter(i -> i % 2 == 0)            .peek(i -> System.out.println("stream map: "+ i))            .mapToInt(i -> i * 2)            .peek(i -> System.out.println("stream sum: "+ i))            .sum();    System.out.println(streamSum);}Run 1:stream filter: 4stream filter: 1stream map: 4stream filter: 2stream sum: 8stream filter: 3stream filter: 5stream map: 2stream sum: 412Run 2:stream filter: 5stream filter: 1stream filter: 3stream filter: 2stream filter: 4stream map: 2stream map: 4stream sum: 4stream sum: 812Run 3:stream filter: 2stream filter: 4stream map: 2stream map: 4stream sum: 8stream filter: 1stream filter: 3stream filter: 5stream sum: 412`

## Use Cases — Filter, Map, Reduce, and Filter/Map/Reduce

`1. Filter even integers into a List2. Multiply the integers by 2 and storing the result in a List3. Sum all the integers into a long4. Filter/Map/Reduce (Filter Evens, Multiply x 2, Sum into long)`

## The Data — 1,000,000 Integers

`private List<Integer> jdkList;private MutableList<Integer> ecList;private IntList ecPrimitiveList;private ExecutorService executorService;@Setuppublic void setup(){    PrimitiveIterator.OfInt intGenerator =         new Random(1L).ints(-1000, 1000).iterator();    this.ecList =         FastList.newWithNValues(1_000_000, intGenerator::nextInt);    this.jdkList = new ArrayList<>(1_000_000);    this.jdkList.addAll(this.ecList);    this.ecPrimitiveList =         this.ecList.collectInt(i -> i, new IntArrayList(1_000_000));    this.executorService = Executors.newWorkStealingPool();}`

## Hardware

`Processor Name: 12-Core Intel Xeon E5Processor Speed: 2.7 GHzNumber of Processors: 1Total Number of Cores: 12L2 Cache (per Core): 256 KBL3 Cache: 30 MBMemory: 64 GB`

## Benchmarking

`public static void main(String[] args) throws RunnerException{    Options options = new OptionsBuilder()        .include(".*" + IntListJMHTest.class.getSimpleName() + ".*")            .forks(2)            .mode(Mode.Throughput)            .timeUnit(TimeUnit.SECONDS)            .warmupIterations(30)            .build();    new Runner(options).run();}`

## Filter even integers

`@Benchmarkpublic MutableList<Integer> filterECBoxedEager(){    return this.ecList.select(i -> i % 2 == 0);}@Benchmarkpublic MutableList<Integer> filterECBoxedLazy(){    return this.ecList            .asLazy()            .select(i -> i % 2 == 0)            .toList();}@Benchmarkpublic MutableList<Integer> filterECParallelEager(){    return ParallelIterate.select(            this.ecList,            i -> i % 2 == 0,            new CompositeFastList<>(),            false);}@Benchmarkpublic MutableList<Integer> filterECParallelLazy(){    return this.ecList            .asParallel(this.executorService, 50_000)            .select(i -> i % 2 == 0)            .toList();}@Benchmarkpublic IntList filterECPrimitiveEager(){    return this.ecPrimitiveList.select(i -> i % 2 == 0);}@Benchmarkpublic IntList filterECPrimitiveLazy(){    return this.ecPrimitiveList            .asLazy()            .select(i -> i % 2 == 0)            .toList();}@Benchmarkpublic List<Integer> filterJDKBoxedParallelStream(){    return this.jdkList            .parallelStream()            .filter(i -> i % 2 == 0)            .collect(Collectors.toList());}@Benchmarkpublic List<Integer> filterJDKBoxedStream(){    return this.jdkList            .stream()            .filter(i -> i % 2 == 0)            .collect(Collectors.toList());}`

## Map each integer x 2

`@Benchmarkpublic MutableList<Integer> mapECBoxedEager(){    return this.ecList.collect(i -> i * 2);}@Benchmarkpublic MutableList<Integer> mapECBoxedLazy(){    return this.ecList            .asLazy()            .collect(i -> i * 2)            .toList();}@Benchmarkpublic MutableList<Integer> mapECParallelEager(){    return ParallelIterate.collect(            this.ecList, i -> i * 2,            new CompositeFastList<>(),            false);}@Benchmarkpublic MutableList<Integer> mapECParallelLazy(){    return this.ecList            .asParallel(this.executorService, 50_000)            .collect(i -> i * 2)            .toList();}@Benchmarkpublic IntList mapECPrimitiveEager(){    return this.ecPrimitiveList            .collectInt(i -> i * 2, IntLists.mutable.empty());}@Benchmarkpublic IntList mapECPrimitiveLazy(){    return this.ecPrimitiveList            .asLazy()            .collectInt(i -> i * 2)            .toList();}@Benchmarkpublic List<Integer> mapJDKBoxedParallelStream(){    return this.jdkList            .parallelStream()            .mapToInt(i -> i * 2)            .boxed()            .collect(Collectors.toList());}@Benchmarkpublic List<Integer> mapJDKBoxedStream(){    return this.jdkList            .stream()            .mapToInt(i -> i * 2)            .boxed()            .collect(Collectors.toList());}`

## Sum all integers

`@Benchmarkpublic long sumECBoxedEager(){    return this.ecList.sumOfInt(Integer::intValue);}@Benchmarkpublic long sumECBoxedLazy(){    return this.ecList            .asLazy()            .sumOfInt(Integer::intValue);}@Benchmarkpublic long sumECParallelEager(){    return ParallelIterate.sumByInt(            this.ecList,            i -> Integer.valueOf(0),            Integer::intValue).get(0);}@Benchmarkpublic long sumECParallelLazy(){    return this.ecList            .asParallel(this.executorService, 50_000)            .sumOfInt(Integer::intValue);}@Benchmarkpublic long sumECPrimitiveEager(){    return this.ecPrimitiveList.sum();}@Benchmarkpublic long sumECPrimitiveLazy(){    return this.ecPrimitiveList            .asLazy()            .sum();}@Benchmarkpublic long sumJDKBoxedParallelStream(){    return this.jdkList            .parallelStream()            .mapToLong(Integer::longValue)            .sum();}@Benchmarkpublic long sumJDKBoxedStream(){    return this.jdkList            .stream()            .mapToLong(Integer::longValue)            .sum();}`

## Filter, Map, Sum

`@Benchmarkpublic long filterMapSumECBoxedEager(){    return this.ecList            .select(i -> i % 2 == 0)            .sumOfInt(i -> i * 2);}@Benchmarkpublic long filterMapSumECBoxedLazy(){    return this.ecList            .asLazy()            .select(i -> i % 2 == 0)            .sumOfInt(i -> i * 2);}@Benchmarkpublic long filterMapSumECOptimizedParallelEager(){    return ParallelIterate.sumByInt(            this.ecList,            i -> i % 2,            i -> i * 2).get(0);}@Benchmarkpublic long filterMapSumECOptimizedParallelLazy(){    return this.ecList            .asParallel(this.executorService, 50_000)            .sumOfInt(i -> i % 2 == 0 ? i * 2 : 0);}@Benchmarkpublic long filterMapSumECParallelLazy(){    return this.ecList            .asParallel(this.executorService, 50_000)            .select(i -> i % 2 == 0)            .sumOfInt(i -> i * 2);}@Benchmarkpublic long filterMapSumECPrimitiveEager(){    return this.ecPrimitiveList            .select(i -> i % 2 == 0)            .collectInt(i -> i * 2, IntLists.mutable.empty())            .sum();}@Benchmarkpublic long filterMapSumECPrimitiveLazy(){    return this.ecPrimitiveList            .asLazy()            .select(i -> i % 2 == 0)            .collectInt(i -> i * 2)            .sum();}@Benchmarkpublic long filterMapSumJDKBoxedParallelStream(){    return this.jdkList            .parallelStream()            .filter(i -> i % 2 == 0)            .mapToLong(i -> (long) (i * 2))            .sum();}@Benchmarkpublic long filterMapSumJDKBoxedStream(){    return this.jdkList            .stream()            .filter(i -> i % 2 == 0)            .mapToLong(i -> (long) (i * 2))            .sum();}`

Written by

## Donald Raab

#### Java Champion. Creator of the Eclipse Collections OSS Java library (http://www.eclipse.org/collections/). Inspired by Smalltalk. Opinions are my own.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just \$5/month. Upgrade