JavaOne – Streams in JDK 8

“Streams in Java 8 – The good, the bad & the ugly”

Speaker: Simon Ritter & Stuart Marks
[Simon has the Twtter handle @speakjava; very cool]

For more blog posts from JavaOne, see the table of contents


Need to think differently. We are used to imperative programming with loops and variables.

Dealing wih exceptions
ugly code – three lines of code and hard to tell what it does

Problems:

  • looks like Perl
  • returns null (vs Optional or empty string)
  • split is called twice so wasted work
  • skipped URLDecoder.decode() because didn’t want to deal with a checked exception – but lost functionality. Problem caused by a missing API in Java so have to use decode.

Better approach:

  • use a method with a try/catch block; call that method from the stream
  • use Map.entry to simulate a tuple
  • Use single char (vs regex) in split. If only pass one character to split, far faster
  • split() is overloaded to take a numeric limit to how many are returned

Imperative streams
inside the for each is a print, and if statement and a LongAdder variable (good for frequent writes and infrequent reads)

then refactored to use mapToInt, a println and an if statement and a local variable. more complicated and still not functional

then switched to peek and no variabe but still an if statement (well a ternary)

finally switched to use a filter and count instead of sum

still not 100% functional because println is a side effect. ok for debugging

[good showing evolution to get functional]

Problems

  • Easy to misuse forEach() because feels familiar. But easily leads to side effects
  • Imperative thinking “for each of these I want to..”
  • Pause to consider if should use for each

Mixing internal and external iteration
for loop running 12 times and then getting data for each month with filter checking Month.of(x) – doesn’t work because x isn’t effectively final

“solve” effectively final by setting to different interim variable

IntStream.range(0,12).forEach – uses internal iteration but forEach. Marginaly better as don’t need interim variable

Instead return a nested map of Month to Map with nested grouping by so only need one iteration – the data stream

Problems

  • Going through data.stream() 12 times
  • forEach cheat
  • array not right data structure; it’s really a map of month to value

Hands on lab question
reduce (“”, (a,b) -> a+b) – works but inefficient because String concatenation

reduce(a,b) -> sb.append(b) – fails because ignores the first letter.

next attempt uses an if statement in reduce

then tried a custom collector. works but more complicated than necessary
Collector.of(StringBuilder::new, StringBuilder::append, StringBuilder::append, StringBuilder::toString

or just use Collectors.joining()

Problems

  • If not using a parameter, it is probably wrong
  • Side effects
  • if stateent version not associative so would fail when run in parallel

Misc

  • can’t use same stream multiple times
  • method references are slightly more efficient than lambdas because lambda gets added into a method in bytecode. Saves a level of indirection by using method reference. But only slightly
  • Calling .sorted() multiple times vs chaining comparing.thenComparing – the later is better [also works because preserves sort :)]
  • parallel streams do more work. might or might not complete faster. uses fork-join pool. number of threads defaults to number of CPUs. In Java9, this is # CPUs for container. On Jaa 8, it was for physical machine
  • Nested parallel streams is bad idea because using same threads so performance is worse. Can create ForkJoinPool if must. Buyer beware; this is an implementation specific behavior and tied to the profile of the machine you write it for.

My take: Fun start to he morning. I like that they covered common things in an entertaining way and not common things. Something to learn for everyone!

JavaOne – Maven BOF

“Maven 5 BOF”

Speaker: Brian Fox, Manfred Moser & Robert Scholte

For more blog posts from JavaOne, see the table of contents


[I was late because we talked more about JUnit 5 after the BOF]

Only 26.4% of Maven Central traffic is from Maven. Nothing else is more than 10% though; not even Ivy or Gradle

Some projects don’t have snapshots; instead every commit is a release

Talked about version ranges. Depends on proximity to your project rather than the latest version. Important to clean up pom dependencies before Java 9 so not in module path. Use Maven dependency plugin (analyze) to find unused ones. Make sure to use latest version of depedency plugin.

Maven won’t generate module descriptor. Different purpose. Not all modules are dependencies. More info in module descriptor. What to export is a decision that needs to be decided by developer. jdeps can generate a rough descriptor to get started based on binaries.

Can have .mvn file inside projects with preferences startig in Maven 3.3.5. For example, you can specify to provide more memory.

Shouldn’t be issues going from 3.3.5 to 3.5.9

Maven (dependency) resolver is now a standalone project

JavaOne – JUnit 5 BOF

“JUnit 5 BOF”

Speaker: Sam Brannen

For more blog posts from JavaOne, see the table of contents


Sam invited us other JUnit presenters at JavaOne to sit on stage with him as a panel. Which was cool. I ot to sit on stage in a Moscone West room!

Sam reviewed/completed from his session earlier today

  • Tests package private
  • Create strings for message in lambda if have on where slow
  • assert timeout
  • Eclipse releases non beta support next week
  • assert all
  • nested tests – good for BDD style so can read as outline/steps with indentation in test report. there’s also an example of the bowling game where the indentation and display names make it easier to follow the output
  • Repeated tests
  • Parameterized tests – values, csv and method sources. Someone wrote an extension for a json source
  • dynamic tests – use lambdas
  • For future releases of JUnit – scenario tests (like in TestNG) where don’t do later steps if earlier fail, test ordering (good for integration tests), parallel execution, option to have new or existing instance for multiple tests, executing in user defined theads, declaration test suites for junit platform (declare which tests to run based on annotations)
  • The name JUnit sucks because we write many types of tests
  • Order of tests is based on hash code of method name since JUnit 4.8. Jupiter would give options.
  • Eclipse only provides a few options to customize which tests run. Maven/Gradle have more
  • Spring 5 – released last week, supports existing features and constructor/method injection, conditional test execution using SpEL expressions (can disable test by OS or date or other conditions – @EnabledIf/@DisabledIf, @ExtendWith(SpringExtension.class) so can use with Mockito or other former runner. @SpringJUnitConfig/@SpringJUnitWebConfig combines spring extension with spring config

Steve Moyer plugged the side project JUnit Pioneer for ope source extensions. Will be building extensions for the JUnit 4 rules that don’t have JUnit 5 equivalents. Also serves as an incubator for JUnit core. Has beta plugin for pi test.

JUnit 5 samples repo shows how to start with Gradle/Maven. Surefire team had non backward compatible change which is why need 2.19 to work. Later version of JUnit 5 will require 2.21+ to avoid this issue.

Starting surefire 2.20, recommend *Tests instead of *Test.