Thread trace

I work with Java 8 threads and would like to come up with a way to debug them. Therefore, I thought that I could write a filter that printed elements at the flow stage, something like this:

int[] nums = {3, -4, 8, 4, -2, 17, 9, -10, 14, 6, -12}; int sum = Arrays.stream(nums) .filter(w -> {System.out.print(" " + w); return true;}) // trace .map(n -> Math.abs(n)) .filter(w -> {System.out.print(" " + w); return true;}) // trace .filter(n -> n % 2 == 0) .distinct() .sum(); System.out.println(sum); 

Close, but this is not entirely true, since it does not have the right delimiters to make it legible:

  3 3 -4 4 8 8 4 4 -2 2 17 17 9 9 -10 10 14 14 6 6 -12 1256 

I want:

 [3, -4, 8, 4, -2, 17, 9, -10, 14, 6, -12] [3 4 8 4 2 17 9 10 14 6 12] 56 

Is there a more standard way to do this? Please note that Peek, as a related article, does not do this because I somehow want to collect all the flow elements at each stage together.

+8
java java-8 java-stream
source share
2 answers

You will need to use a different list for each breakpoint.

Normally, I would not recommend using streaming operations to change state this way, but for debugging purposes, I think everything is fine. In fact, as @BrianGoetz points out below, debugging was the reason for adding peek .

 int[] nums = {3, -4, 8, 4, -2, 17, 9, -10, 14, 6, -12}; List<Integer> checkPoint1 = new ArrayList<>(); List<Integer> checkPoint2 = new ArrayList<>(); List<Integer> checkPoint3 = new ArrayList<>(); List<Integer> checkPoint4 = new ArrayList<>(); int sum = Arrays.stream(nums) .peek(checkPoint1::add) .map(n -> Math.abs(n)) .peek(checkPoint2::add) .filter(n -> n % 2 == 0) .peek(checkPoint3::add) .distinct() .peek(checkPoint4::add) .sum(); System.out.println(checkPoint1); System.out.println(checkPoint2); System.out.println(checkPoint3); System.out.println(checkPoint4); System.out.println(sum); 

Output:

 [3, -4, 8, 4, -2, 17, 9, -10, 14, 6, -12] [3, 4, 8, 4, 2, 17, 9, 10, 14, 6, 12] [4, 8, 4, 2, 10, 14, 6, 12] [4, 8, 2, 10, 14, 6, 12] 56 
+9
source share

If you often need Paul’s solution, then you can write a static shell function that generates peek indexed functions:

 int sum = streamDebugger<Integer>((Supplier<Consumer<?>> peekGen) => { return Arrays.stream(nums) .peek(peekGen.get()) .map(n -> Math.abs(n)) .peek(peekGen.get()) .filter(n -> n % 2 == 0) .peek(peekGen.get()) .distinct() .peek(peekGen.get()) .sum(); }) 

To automate this step further, one could even wrap the entire flow interface so that each method of a specific interface returns a wrapped implementation that automatically scans each step in the pipeline:

 int sum = debugIntStream(Arrays.stream(nums)) .map(n -> Math.abs(n)) .filter(n -> n % 2 == 0) .distinct() .sum(); 

Since the implementation would be rather tedious and, I hope, would not be necessary, the implementation would remain to the reader.

+6
source share

All Articles