For CPU-intensive operations on large datasets, parallel streams automatically split work across multiple cores. Understanding when parallelism helps (and when it hurts) is essential for writing performant stream code.

Creating Parallel Streams

Convert any stream to parallel processing with a single method call.

rangeEnd
Create.java
Replay: real traced execution (multi-file project)
import java.util.*;
import java.util.stream.*;

public class Create {
    public static void main(String[] args) {
        int rangeEnd = 11;
        List<Integer> nums = IntStream.range(1, rangeEnd).boxed().toList();

        List<Integer> fromParallelStream = nums.parallelStream()
                .map(n -> n)
                .collect(Collectors.toList());
        System.out.println("parallelStream: " + fromParallelStream);

        List<Integer> fromParallel = nums.stream()
                .parallel()
                .map(n -> n)
                .collect(Collectors.toList());
        System.out.println("stream().parallel(): " + fromParallel);

        boolean isParallel = nums.parallelStream().isParallel();
        System.out.println("isParallel: " + isParallel);

    }
}
import java.util.*;
import java.util.stream.*;

public class Create {
    public static void main(String[] args) {
        int rangeEnd = 6;
        List<Integer> nums = IntStream.range(1, rangeEnd).boxed().toList();

        List<Integer> fromParallelStream = nums.parallelStream()
                .map(n -> n)
                .collect(Collectors.toList());
        System.out.println("parallelStream: " + fromParallelStream);

        List<Integer> fromParallel = nums.stream()
                .parallel()
                .map(n -> n)
                .collect(Collectors.toList());
        System.out.println("stream().parallel(): " + fromParallel);

        boolean isParallel = nums.parallelStream().isParallel();
        System.out.println("isParallel: " + isParallel);

    }
}
import java.util.*;
import java.util.stream.*;

public class Create {
    public static void main(String[] args) {
        int rangeEnd = 16;
        List<Integer> nums = IntStream.range(1, rangeEnd).boxed().toList();

        List<Integer> fromParallelStream = nums.parallelStream()
                .map(n -> n)
                .collect(Collectors.toList());
        System.out.println("parallelStream: " + fromParallelStream);

        List<Integer> fromParallel = nums.stream()
                .parallel()
                .map(n -> n)
                .collect(Collectors.toList());
        System.out.println("stream().parallel(): " + fromParallel);

        boolean isParallel = nums.parallelStream().isParallel();
        System.out.println("isParallel: " + isParallel);

    }
}
  1. rangeEnd ← 11, nums ← [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], fromParallelStream ← [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    4public class Create {5    public static void main(String[] args) {6        int rangeEnd→ 11 = 11; //@rangeEnd=11, 6, 167        List<Integer> nums→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] = IntStream.range(1, rangeEnd11).boxed().toList();89        List<Integer> fromParallelStream→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] = nums.parallelStream()10                .map(n -> n)11                .collect(Collectors.toList());12        System.out.println("parallelStream: " + fromParallelStream[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);1314        List<Integer> fromParallel→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] = nums.stream()15                .parallel()16                .map(n -> n)17                .collect(Collectors.toList());18        System.out.println("stream().parallel(): " + fromParallel[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);1920        boolean isParallel→ true = nums.parallelStream().isParallel();21        System.out.println("isParallel: " + isParalleltrue);
    outputparallelStream: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    stream().parallel(): [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    isParallel: true
  1. rangeEnd ← 6, nums ← [1, 2, 3, 4, 5], fromParallelStream ← [1, 2, 3, 4, 5]

    4public class Create {5    public static void main(String[] args) {6        int rangeEnd→ 6 = 6;7        List<Integer> nums→ [1, 2, 3, 4, 5] = IntStream.range(1, rangeEnd6).boxed().toList();89        List<Integer> fromParallelStream→ [1, 2, 3, 4, 5] = nums.parallelStream()10                .map(n -> n)11                .collect(Collectors.toList());12        System.out.println("parallelStream: " + fromParallelStream[1, 2, 3, 4, 5]);1314        List<Integer> fromParallel→ [1, 2, 3, 4, 5] = nums.stream()15                .parallel()16                .map(n -> n)17                .collect(Collectors.toList());18        System.out.println("stream().parallel(): " + fromParallel[1, 2, 3, 4, 5]);1920        boolean isParallel→ true = nums.parallelStream().isParallel();21        System.out.println("isParallel: " + isParalleltrue);
    outputparallelStream: [1, 2, 3, 4, 5]
    stream().parallel(): [1, 2, 3, 4, 5]
    isParallel: true
  1. rangeEnd ← 16, nums ← [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

    4public class Create {5    public static void main(String[] args) {6        int rangeEnd→ 16 = 16;7        List<Integer> nums→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] = IntStream.range(1, rangeEnd16).boxed().toList();89        List<Integer> fromParallelStream→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] = nums.parallelStream()10                .map(n -> n)11                .collect(Collectors.toList());12        System.out.println("parallelStream: " + fromParallelStream[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);1314        List<Integer> fromParallel→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] = nums.stream()15                .parallel()16                .map(n -> n)17                .collect(Collectors.toList());18        System.out.println("stream().parallel(): " + fromParallel[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);1920        boolean isParallel→ true = nums.parallelStream().isParallel();21        System.out.println("isParallel: " + isParalleltrue);
    outputparallelStream: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
    stream().parallel(): [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
    isParallel: true
parallel stream A stream that processes elements concurrently across multiple threads using the fork/join framework.
spliterator The mechanism that divides stream data into chunks for parallel processing; some data structures split better than others.

Performance Considerations

Parallel streams have overhead. They help with large datasets and CPU-bound work, but can hurt performance otherwise.

rangeEnd
Performance.java
Replay: real traced execution (multi-file project)
import java.util.*;
import java.util.stream.*;

public class Performance {
    private static int work(int n) {
        int result = 0;
        for (int i = 1; i <= 5; i++) {
            result += n * i;
        }
        return result;
    }

    public static void main(String[] args) {
        int rangeEnd = 8;
        List<Integer> nums = IntStream.range(1, rangeEnd).boxed().toList();

        List<Integer> sequential = nums.stream()
                .map(Performance::work)
                .collect(Collectors.toList());
        System.out.println("sequential size: " + sequential.size());

        List<Integer> parallel = nums.parallelStream()
                .map(Performance::work)
                .collect(Collectors.toList());
        System.out.println("parallel size: " + parallel.size());

        boolean sameResults = sequential.equals(parallel);
        System.out.println("sameResults: " + sameResults);
    }
}
import java.util.*;
import java.util.stream.*;

public class Performance {
    private static int work(int n) {
        int result = 0;
        for (int i = 1; i <= 5; i++) {
            result += n * i;
        }
        return result;
    }

    public static void main(String[] args) {
        int rangeEnd = 5;
        List<Integer> nums = IntStream.range(1, rangeEnd).boxed().toList();

        List<Integer> sequential = nums.stream()
                .map(Performance::work)
                .collect(Collectors.toList());
        System.out.println("sequential size: " + sequential.size());

        List<Integer> parallel = nums.parallelStream()
                .map(Performance::work)
                .collect(Collectors.toList());
        System.out.println("parallel size: " + parallel.size());

        boolean sameResults = sequential.equals(parallel);
        System.out.println("sameResults: " + sameResults);
    }
}
import java.util.*;
import java.util.stream.*;

public class Performance {
    private static int work(int n) {
        int result = 0;
        for (int i = 1; i <= 5; i++) {
            result += n * i;
        }
        return result;
    }

    public static void main(String[] args) {
        int rangeEnd = 11;
        List<Integer> nums = IntStream.range(1, rangeEnd).boxed().toList();

        List<Integer> sequential = nums.stream()
                .map(Performance::work)
                .collect(Collectors.toList());
        System.out.println("sequential size: " + sequential.size());

        List<Integer> parallel = nums.parallelStream()
                .map(Performance::work)
                .collect(Collectors.toList());
        System.out.println("parallel size: " + parallel.size());

        boolean sameResults = sequential.equals(parallel);
        System.out.println("sameResults: " + sameResults);
    }
}
  1. rangeEnd ← 8, nums ← [1, 2, 3, 4, 5, 6, 7]

    13public static void main(String[] args) {14    int rangeEnd→ 8 = 8; //@rangeEnd=8, 5, 1115    List<Integer> nums→ [1, 2, 3, 4, 5, 6, 7] = IntStream.range(1, rangeEnd8).boxed().toList();1617    List<Integer> sequential = nums.stream()18            .map(Performance::work)19            .collect(Collectors.toList());20    System.out.println("sequential size: " + sequential.size());
  2. result ← 0

    pass 1 of 14
    4public class Performance {5    private static int work(int n1) {6        int result→ 0 = 0;7        for (int i = 1; i <= 5; i++) {
    14 passes — pass 1 is the card above
    passnresult
    110
    220
    330
    440
    550
    660
    770
    850
    97
    ⋯ 3 more passes ⋯
    1320
    1410
  3. result ← 1

    pass 1 of 70
    6int result = 0;7for (int i1 = 1; i <= 5; i++) {8    result→ 1 += n1 * i1;9}
    70 passes — pass 1 is the card above
    passinresult
    1110 1
    2211 3
    3313 6
    4416 10
    55110 15
    6120 2
    7222 6
    8326 12
    94212 20
    ⋯ 59 more passes ⋯
    694742 70
    705770 105
  4. return result;

    9    }10    return result15;11}
  5. return result;

    9    }10    return result30;11}
  6. return result;

    9    }10    return result45;11}
  7. return result;

    9    }10    return result60;11}
  8. return result;

    9    }10    return result75;11}
  9. return result;

    9    }10    return result90;11}
  10. return result;

    9    }10    return result105;11}
  11. sequential ← [15, 30, 45, 60, 75, 90, 105]

    17List<Integer> sequential→ [15, 30, 45, 60, 75, 90, 105] = nums.stream()18        .map(Performance::work)19        .collect(Collectors.toList());20System.out.println("sequential size: " + sequential.size());2122List<Integer> parallel = nums.parallelStream()23        .map(Performance::work)24        .collect(Collectors.toList());25System.out.println("parallel size: " + parallel.size());
    outputsequential size: 7
  12. return result;

    9    }10    return result75;11}
  13. return result;

    9    }10    return result60;11}
  14. return result;

    9    }10    return result45;11}
  15. return result;

    9    }10    return result90;11}
  16. return result;

    9    }10    return result30;11}
  17. return result;

    9    }10    return result15;11}
  18. return result;

    9    }10    return result105;11}
  19. parallel ← [15, 30, 45, 60, 75, 90, 105], sameResults ← true

    22    List<Integer> parallel→ [15, 30, 45, 60, 75, 90, 105] = nums.parallelStream()23            .map(Performance::work)24            .collect(Collectors.toList());25    System.out.println("parallel size: " + parallel.size());2627    boolean sameResults→ true = sequential.equals(parallel[15, 30, 45, 60, 75, 90, 105]);28    System.out.println("sameResults: " + sameResultstrue);29}
    outputparallel size: 7
    sameResults: true
  1. rangeEnd ← 5, nums ← [1, 2, 3, 4]

    13public static void main(String[] args) {14    int rangeEnd→ 5 = 5;15    List<Integer> nums→ [1, 2, 3, 4] = IntStream.range(1, rangeEnd5).boxed().toList();1617    List<Integer> sequential = nums.stream()18            .map(Performance::work)19            .collect(Collectors.toList());20    System.out.println("sequential size: " + sequential.size());
  2. result ← 0

    pass 1 of 8
    4public class Performance {5    private static int work(int n1) {6        int result→ 0 = 0;7        for (int i = 1; i <= 5; i++) {
    All 8 passes — pass 1 is the card above
    passnresult
    110
    220
    330
    440
    530
    640
    71
    820
  3. result ← 1

    pass 1 of 40
    6int result = 0;7for (int i1 = 1; i <= 5; i++) {8    result→ 1 += n1 * i1;9}
    40 passes — pass 1 is the card above
    passresultni
    10 111
    21 312
    33 613
    46 1014
    510 1515
    60 221
    72 622
    86 1223
    912 2024
    ⋯ 29 more passes ⋯
    3920 3025
    4010 1515
  4. return result;

    9    }10    return result15;11}
  5. return result;

    9    }10    return result30;11}
  6. return result;

    9    }10    return result45;11}
  7. return result;

    9    }10    return result60;11}
  8. sequential ← [15, 30, 45, 60]

    17List<Integer> sequential→ [15, 30, 45, 60] = nums.stream()18        .map(Performance::work)19        .collect(Collectors.toList());20System.out.println("sequential size: " + sequential.size());2122List<Integer> parallel = nums.parallelStream()23        .map(Performance::work)24        .collect(Collectors.toList());25System.out.println("parallel size: " + parallel.size());
    outputsequential size: 4
  9. return result;

    9    }10    return result45;11}
  10. return result;

    9    }10    return result30;11}
  11. result ← 60

    7for (int i = 1; i <= 5; i++) {8    result→ 60 += n1 * i4;9}
  12. return result;

    9    }10    return result60;11}
  13. result ← 10

    7for (int i = 1; i <= 5; i++) {8    result→ 10 += n1 * i4;9}
  14. return result;

    9    }10    return result15;11}
  15. parallel ← [15, 30, 45, 60], sameResults ← true

    22    List<Integer> parallel→ [15, 30, 45, 60] = nums.parallelStream()23            .map(Performance::work)24            .collect(Collectors.toList());25    System.out.println("parallel size: " + parallel.size());2627    boolean sameResults→ true = sequential.equals(parallel[15, 30, 45, 60]);28    System.out.println("sameResults: " + sameResultstrue);29}
    outputparallel size: 4
    sameResults: true
  1. rangeEnd ← 11, nums ← [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    13public static void main(String[] args) {14    int rangeEnd→ 11 = 11;15    List<Integer> nums→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] = IntStream.range(1, rangeEnd11).boxed().toList();1617    List<Integer> sequential = nums.stream()18            .map(Performance::work)19            .collect(Collectors.toList());20    System.out.println("sequential size: " + sequential.size());
  2. result ← 0

    pass 1 of 20
    4public class Performance {5    private static int work(int n1) {6        int result→ 0 = 0;7        for (int i = 1; i <= 5; i++) {
    20 passes — pass 1 is the card above
    passresultni
    101
    202
    303
    404
    505
    606
    707
    808
    909
    ⋯ 9 more passes ⋯
    1908
    20010
  3. result ← 1

    pass 1 of 100
    6int result = 0;7for (int i1 = 1; i <= 5; i++) {8    result→ 1 += n1 * i1;9}
    100 passes — pass 1 is the card above
    passresultni
    10 111
    21 312
    33 613
    46 1014
    510 1515
    60 221
    72 622
    86 1223
    912 2024
    ⋯ 89 more passes ⋯
    9954 9094
    10090 13595
  4. return result;

    9    }10    return result15;11}
  5. return result;

    9    }10    return result30;11}
  6. return result;

    9    }10    return result45;11}
  7. return result;

    9    }10    return result60;11}
  8. return result;

    9    }10    return result75;11}
  9. return result;

    9    }10    return result90;11}
  10. return result;

    9    }10    return result105;11}
  11. return result;

    9    }10    return result120;11}
  12. return result;

    9    }10    return result135;11}
  13. return result;

    9    }10    return result150;11}
  14. sequential ← [15, 30, 45, 60, 75, 90, 105, 120, 135, 150]

    17List<Integer> sequential→ [15, 30, 45, 60, 75, 90, 105, 120, 135, 150] = nums.stream()18        .map(Performance::work)19        .collect(Collectors.toList());20System.out.println("sequential size: " + sequential.size());2122List<Integer> parallel = nums.parallelStream()23        .map(Performance::work)24        .collect(Collectors.toList());25System.out.println("parallel size: " + parallel.size());
    outputsequential size: 10
  15. return result;

    9    }10    return result30;11}
  16. return result;

    9    }10    return result15;11}
  17. return result;

    9    }10    return result105;11}
  18. result ← 50

    7for (int i = 1; i <= 5; i++) {8    result→ 50 += n5 * i4;9}
  19. return result;

    9    }10    return result75;11}
  20. return result;

    9    }10    return result45;11}
  21. return result;

    9    }10    return result90;11}
  22. return result;

    9    }10    return result120;11}
  23. return result;

    9    }10    return result150;11}
  24. return result;

    9    }10    return result135;11}
  25. return result;

    9    }10    return result60;11}
  26. parallel ← [15, 30, 45, 60, 75, 90, 105, 120, 135, 150], sameResults ← true

    22    List<Integer> parallel→ [15, 30, 45, 60, 75, 90, 105, 120, 135, 150] = nums.parallelStream()23            .map(Performance::work)24            .collect(Collectors.toList());25    System.out.println("parallel size: " + parallel.size());2627    boolean sameResults→ true = sequential.equals(parallel[15, 30, 45, 60, 75, 90, 105, 120, 135, 150]);28    System.out.println("sameResults: " + sameResultstrue);29}
    outputparallel size: 10
    sameResults: true

Ordering in Parallel Streams

Parallel streams may process elements out of order. Use forEachOrdered when order matters for output.

rangeEnd
Order.java
Replay: real traced execution (multi-file project)
import java.util.*;
import java.util.stream.*;

public class Order {
    public static void main(String[] args) {
        int rangeEnd = 11;
        List<Integer> nums = IntStream.range(1, rangeEnd).boxed().toList();

        List<Integer> collected = nums.parallelStream()
                .map(n -> n)
                .collect(Collectors.toList());
        System.out.println("collect: " + collected);

        System.out.print("forEachOrdered: ");
        nums.parallelStream().forEachOrdered(n -> System.out.print(n + " "));
        System.out.println();

        List<Integer> result = nums.parallelStream()
                .map(n -> n * 2)
                .collect(Collectors.toList());
        System.out.println("collect: " + result);

    }
}
import java.util.*;
import java.util.stream.*;

public class Order {
    public static void main(String[] args) {
        int rangeEnd = 6;
        List<Integer> nums = IntStream.range(1, rangeEnd).boxed().toList();

        List<Integer> collected = nums.parallelStream()
                .map(n -> n)
                .collect(Collectors.toList());
        System.out.println("collect: " + collected);

        System.out.print("forEachOrdered: ");
        nums.parallelStream().forEachOrdered(n -> System.out.print(n + " "));
        System.out.println();

        List<Integer> result = nums.parallelStream()
                .map(n -> n * 2)
                .collect(Collectors.toList());
        System.out.println("collect: " + result);

    }
}
import java.util.*;
import java.util.stream.*;

public class Order {
    public static void main(String[] args) {
        int rangeEnd = 16;
        List<Integer> nums = IntStream.range(1, rangeEnd).boxed().toList();

        List<Integer> collected = nums.parallelStream()
                .map(n -> n)
                .collect(Collectors.toList());
        System.out.println("collect: " + collected);

        System.out.print("forEachOrdered: ");
        nums.parallelStream().forEachOrdered(n -> System.out.print(n + " "));
        System.out.println();

        List<Integer> result = nums.parallelStream()
                .map(n -> n * 2)
                .collect(Collectors.toList());
        System.out.println("collect: " + result);

    }
}
  1. rangeEnd ← 11, nums ← [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], collected ← [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    4public class Order {5    public static void main(String[] args) {6        int rangeEnd→ 11 = 11; //@rangeEnd=11, 6, 167        List<Integer> nums→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] = IntStream.range(1, rangeEnd11).boxed().toList();89        List<Integer> collected→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] = nums.parallelStream()10                .map(n -> n)11                .collect(Collectors.toList());12        System.out.println("collect: " + collected[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);1314        System.out.print("forEachOrdered: ");15        nums.parallelStream().forEachOrdered(n -> System.out.print(n + " "));16        System.out.println();1718        List<Integer> result→ [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] = nums.parallelStream()19                .map(n -> n * 2)20                .collect(Collectors.toList());21        System.out.println("collect: " + result[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
    outputcollect: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    forEachOrdered:
    collect: [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
  1. rangeEnd ← 6, nums ← [1, 2, 3, 4, 5], collected ← [1, 2, 3, 4, 5]

    4public class Order {5    public static void main(String[] args) {6        int rangeEnd→ 6 = 6;7        List<Integer> nums→ [1, 2, 3, 4, 5] = IntStream.range(1, rangeEnd6).boxed().toList();89        List<Integer> collected→ [1, 2, 3, 4, 5] = nums.parallelStream()10                .map(n -> n)11                .collect(Collectors.toList());12        System.out.println("collect: " + collected[1, 2, 3, 4, 5]);1314        System.out.print("forEachOrdered: ");15        nums.parallelStream().forEachOrdered(n -> System.out.print(n + " "));16        System.out.println();1718        List<Integer> result→ [2, 4, 6, 8, 10] = nums.parallelStream()19                .map(n -> n * 2)20                .collect(Collectors.toList());21        System.out.println("collect: " + result[2, 4, 6, 8, 10]);
    outputcollect: [1, 2, 3, 4, 5]
    forEachOrdered:
    collect: [2, 4, 6, 8, 10]
  1. rangeEnd ← 16, nums ← [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

    4public class Order {5    public static void main(String[] args) {6        int rangeEnd→ 16 = 16;7        List<Integer> nums→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] = IntStream.range(1, rangeEnd16).boxed().toList();89        List<Integer> collected→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] = nums.parallelStream()10                .map(n -> n)11                .collect(Collectors.toList());12        System.out.println("collect: " + collected[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);1314        System.out.print("forEachOrdered: ");15        nums.parallelStream().forEachOrdered(n -> System.out.print(n + " "));16        System.out.println();1718        List<Integer> result→ [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30] = nums.parallelStream()19                .map(n -> n * 2)20                .collect(Collectors.toList());21        System.out.println("collect: " + result[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]);
    outputcollect: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
    forEachOrdered:
    collect: [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]
encounter order The defined sequence of elements in a stream; parallel operations may process out of order but can preserve order in results.

Avoiding Shared Mutable State

Shared mutable state in parallel streams causes race conditions. Keep operations stateless.

rangeEnd
SharedState.java
Replay: real traced execution (multi-file project)
import java.util.*;
import java.util.stream.*;

public class SharedState {
    public static void main(String[] args) {
        int rangeEnd = 101;
        List<Integer> nums = IntStream.range(1, rangeEnd).boxed().toList();

        List<Integer> sideEffectResult = Collections.synchronizedList(new ArrayList<>());
        nums.parallelStream()
                .filter(n -> n % 2 == 0)
                .forEach(sideEffectResult::add);
        Collections.sort(sideEffectResult);
        System.out.println("sideEffectResult size: " + sideEffectResult.size());

        List<Integer> correctResult = nums.parallelStream()
                .filter(n -> n % 2 == 0)
                .collect(Collectors.toList());
        System.out.println("correctResult size: " + correctResult.size());

    }
}
import java.util.*;
import java.util.stream.*;

public class SharedState {
    public static void main(String[] args) {
        int rangeEnd = 21;
        List<Integer> nums = IntStream.range(1, rangeEnd).boxed().toList();

        List<Integer> sideEffectResult = Collections.synchronizedList(new ArrayList<>());
        nums.parallelStream()
                .filter(n -> n % 2 == 0)
                .forEach(sideEffectResult::add);
        Collections.sort(sideEffectResult);
        System.out.println("sideEffectResult size: " + sideEffectResult.size());

        List<Integer> correctResult = nums.parallelStream()
                .filter(n -> n % 2 == 0)
                .collect(Collectors.toList());
        System.out.println("correctResult size: " + correctResult.size());

    }
}
import java.util.*;
import java.util.stream.*;

public class SharedState {
    public static void main(String[] args) {
        int rangeEnd = 501;
        List<Integer> nums = IntStream.range(1, rangeEnd).boxed().toList();

        List<Integer> sideEffectResult = Collections.synchronizedList(new ArrayList<>());
        nums.parallelStream()
                .filter(n -> n % 2 == 0)
                .forEach(sideEffectResult::add);
        Collections.sort(sideEffectResult);
        System.out.println("sideEffectResult size: " + sideEffectResult.size());

        List<Integer> correctResult = nums.parallelStream()
                .filter(n -> n % 2 == 0)
                .collect(Collectors.toList());
        System.out.println("correctResult size: " + correctResult.size());

    }
}
  1. rangeEnd ← 101, nums ← [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]

    4public class SharedState {5    public static void main(String[] args) {6        int rangeEnd→ 101 = 101; //@rangeEnd=101, 21, 5017        List<Integer> nums→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] = IntStream.range(1, rangeEnd101).boxed().toList();89        List<Integer> sideEffectResult→ [] = Collections.synchronizedList(new ArrayList<>());10        nums.parallelStream()11                .filter(n -> n % 2 == 0)12                .forEach(sideEffectResult::add);13        Collections.sort(sideEffectResult→ [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100]);14        System.out.println("sideEffectResult size: " + sideEffectResult.size());1516        List<Integer> correctResult→ [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100] = nums.parallelStream()17                .filter(n -> n % 2 == 0)18                .collect(Collectors.toList());19        System.out.println("correctResult size: " + correctResult.size());
    outputsideEffectResult size: 50
    correctResult size: 50
  1. rangeEnd ← 21, nums ← [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

    4public class SharedState {5    public static void main(String[] args) {6        int rangeEnd→ 21 = 21;7        List<Integer> nums→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] = IntStream.range(1, rangeEnd21).boxed().toList();89        List<Integer> sideEffectResult→ [] = Collections.synchronizedList(new ArrayList<>());10        nums.parallelStream()11                .filter(n -> n % 2 == 0)12                .forEach(sideEffectResult::add);13        Collections.sort(sideEffectResult→ [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);14        System.out.println("sideEffectResult size: " + sideEffectResult.size());1516        List<Integer> correctResult→ [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] = nums.parallelStream()17                .filter(n -> n % 2 == 0)18                .collect(Collectors.toList());19        System.out.println("correctResult size: " + correctResult.size());
    outputsideEffectResult size: 10
    correctResult size: 10
  1. rangeEnd ← 501, nums ← [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500]

    4public class SharedState {5    public static void main(String[] args) {6        int rangeEnd→ 501 = 501;7        List<Integer> nums→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500] = IntStream.range(1, rangeEnd501).boxed().toList();89        List<Integer> sideEffectResult→ [] = Collections.synchronizedList(new ArrayList<>());10        nums.parallelStream()11                .filter(n -> n % 2 == 0)12                .forEach(sideEffectResult::add);13        Collections.sort(sideEffectResult→ [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, 448, 450, 452, 454, 456, 458, 460, 462, 464, 466, 468, 470, 472, 474, 476, 478, 480, 482, 484, 486, 488, 490, 492, 494, 496, 498, 500]);14        System.out.println("sideEffectResult size: " + sideEffectResult.size());1516        List<Integer> correctResult→ [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, 448, 450, 452, 454, 456, 458, 460, 462, 464, 466, 468, 470, 472, 474, 476, 478, 480, 482, 484, 486, 488, 490, 492, 494, 496, 498, 500] = nums.parallelStream()17                .filter(n -> n % 2 == 0)18                .collect(Collectors.toList());19        System.out.println("correctResult size: " + correctResult.size());
    outputsideEffectResult size: 250
    correctResult size: 250
thread safety Code that behaves correctly when accessed by multiple threads simultaneously; parallel streams require stateless operations.

Combiners for Parallel Reduce

When reducing in parallel, provide a combiner to merge partial results from different threads.

rangeEnd
Combiners.java
Replay: real traced execution (multi-file project)
import java.util.*;
import java.util.stream.*;

public class Combiners {
    public static void main(String[] args) {
        int rangeEnd = 101;
        List<Integer> nums = IntStream.range(1, rangeEnd).boxed().toList();

        int sum = nums.parallelStream()
                .reduce(0, Integer::sum, Integer::sum);
        System.out.println("sum: " + sum);

        List<Integer> evens = nums.parallelStream()
                .filter(n -> n % 2 == 0)
                .collect(
                        ArrayList::new,
                        ArrayList::add,
                        ArrayList::addAll // combiner
                );
        System.out.println("evens count: " + evens.size());

        Map<Integer, List<Integer>> byMod = nums.parallelStream()
                .collect(Collectors.groupingBy(n -> n % 5, TreeMap::new, Collectors.toList()));
        System.out.println("byMod: " + byMod.keySet());

    }
}
import java.util.*;
import java.util.stream.*;

public class Combiners {
    public static void main(String[] args) {
        int rangeEnd = 11;
        List<Integer> nums = IntStream.range(1, rangeEnd).boxed().toList();

        int sum = nums.parallelStream()
                .reduce(0, Integer::sum, Integer::sum);
        System.out.println("sum: " + sum);

        List<Integer> evens = nums.parallelStream()
                .filter(n -> n % 2 == 0)
                .collect(
                        ArrayList::new,
                        ArrayList::add,
                        ArrayList::addAll // combiner
                );
        System.out.println("evens count: " + evens.size());

        Map<Integer, List<Integer>> byMod = nums.parallelStream()
                .collect(Collectors.groupingBy(n -> n % 5, TreeMap::new, Collectors.toList()));
        System.out.println("byMod: " + byMod.keySet());

    }
}
import java.util.*;
import java.util.stream.*;

public class Combiners {
    public static void main(String[] args) {
        int rangeEnd = 51;
        List<Integer> nums = IntStream.range(1, rangeEnd).boxed().toList();

        int sum = nums.parallelStream()
                .reduce(0, Integer::sum, Integer::sum);
        System.out.println("sum: " + sum);

        List<Integer> evens = nums.parallelStream()
                .filter(n -> n % 2 == 0)
                .collect(
                        ArrayList::new,
                        ArrayList::add,
                        ArrayList::addAll // combiner
                );
        System.out.println("evens count: " + evens.size());

        Map<Integer, List<Integer>> byMod = nums.parallelStream()
                .collect(Collectors.groupingBy(n -> n % 5, TreeMap::new, Collectors.toList()));
        System.out.println("byMod: " + byMod.keySet());

    }
}
  1. rangeEnd ← 101, nums ← [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]

    4public class Combiners {5    public static void main(String[] args) {6        int rangeEnd→ 101 = 101; //@rangeEnd=101, 11, 517        List<Integer> nums→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] = IntStream.range(1, rangeEnd101).boxed().toList();89        int sum→ 5050 = nums.parallelStream()10                .reduce(0, Integer::sum, Integer::sum);11        System.out.println("sum: " + sum5050);1213        List<Integer> evens→ [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100] = nums.parallelStream()14                .filter(n -> n % 2 == 0)15                .collect(16                        ArrayList::new,17                        ArrayList::add,18                        ArrayList::addAll // combiner19                );20        System.out.println("evens count: " + evens.size());2122        Map<Integer, List<Integer>> byMod→ {0=[5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100], 1=[1, 6, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56, 61, 66, 71, 76, 81, 86, 91, 96], 2=[2, 7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72, 77, 82, 87, 92, 97], 3=[3, 8, 13, 18, 23, 28, 33, 38, 43, 48, 53, 58, 63, 68, 73, 78, 83, 88, 93, 98], 4=[4, 9, 14, 19, 24, 29, 34, 39, 44, 49, 54, 59, 64, 69, 74, 79, 84, 89, 94, 99]} = nums.parallelStream()23                .collect(Collectors.groupingBy(n -> n % 5, TreeMap::new, Collectors.toList()));24        System.out.println("byMod: " + byMod.keySet());
    outputsum: 5050
    evens count: 50
    byMod: [0, 1, 2, 3, 4]
  1. rangeEnd ← 11, nums ← [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], sum ← 55

    4public class Combiners {5    public static void main(String[] args) {6        int rangeEnd→ 11 = 11;7        List<Integer> nums→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] = IntStream.range(1, rangeEnd11).boxed().toList();89        int sum→ 55 = nums.parallelStream()10                .reduce(0, Integer::sum, Integer::sum);11        System.out.println("sum: " + sum55);1213        List<Integer> evens→ [2, 4, 6, 8, 10] = nums.parallelStream()14                .filter(n -> n % 2 == 0)15                .collect(16                        ArrayList::new,17                        ArrayList::add,18                        ArrayList::addAll // combiner19                );20        System.out.println("evens count: " + evens.size());2122        Map<Integer, List<Integer>> byMod→ {0=[5, 10], 1=[1, 6], 2=[2, 7], 3=[3, 8], 4=[4, 9]} = nums.parallelStream()23                .collect(Collectors.groupingBy(n -> n % 5, TreeMap::new, Collectors.toList()));24        System.out.println("byMod: " + byMod.keySet());
    outputsum: 55
    evens count: 5
    byMod: [0, 1, 2, 3, 4]
  1. rangeEnd ← 51, nums ← [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50]

    4public class Combiners {5    public static void main(String[] args) {6        int rangeEnd→ 51 = 51;7        List<Integer> nums→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50] = IntStream.range(1, rangeEnd51).boxed().toList();89        int sum→ 1275 = nums.parallelStream()10                .reduce(0, Integer::sum, Integer::sum);11        System.out.println("sum: " + sum1275);1213        List<Integer> evens→ [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50] = nums.parallelStream()14                .filter(n -> n % 2 == 0)15                .collect(16                        ArrayList::new,17                        ArrayList::add,18                        ArrayList::addAll // combiner19                );20        System.out.println("evens count: " + evens.size());2122        Map<Integer, List<Integer>> byMod→ {0=[5, 10, 15, 20, 25, 30, 35, 40, 45, 50], 1=[1, 6, 11, 16, 21, 26, 31, 36, 41, 46], 2=[2, 7, 12, 17, 22, 27, 32, 37, 42, 47], 3=[3, 8, 13, 18, 23, 28, 33, 38, 43, 48], 4=[4, 9, 14, 19, 24, 29, 34, 39, 44, 49]} = nums.parallelStream()23                .collect(Collectors.groupingBy(n -> n % 5, TreeMap::new, Collectors.toList()));24        System.out.println("byMod: " + byMod.keySet());
    outputsum: 1275
    evens count: 25
    byMod: [0, 1, 2, 3, 4]

Exercise: Practical.java

Compare sequential vs parallel performance for computing statistics on a large dataset