Streams provide a reinvention of the standard Java processing model. Instead of working directly on
data, your program builds up a set of instructions about how to work the stream. These instructions can
range from simple filtering and conversion rules to complex map/reduce structures and everything in
between. They work by passing functions onto the methods of the Stream object.
For instance, in the FunJava library, 14 there is a JdbcTemplate-like class that provides the results as a
stream of ResultMap objects. These objects are the raw JDBC object types that come out of the database,
indexed by column name and by column index. Whatever you want to do with the data is up to you. The great
news is that the JVM will automatically optimize the stream processing in order to keep your memory load
down and your concurrent processes up: this means that the JVM is getting efficiency out of your code for free!
Say that you queried the database, and for some reason you couldn't do reasonable SQL work in the
database, but had to do it programmatically instead. (I wish this were as hypothetical as it sounds.) Perhaps
you wanted to find the salary statistics for people whose first name was “Robert.” The stream code for this
using the FunJava library is given in Listing 1-13. This example demonstrates how lambdas and streams
work together to make expressive code. The JVM has a lot of freedom to implement that code, as well, which
enables it to make significant optimizations on our behalf. In Chapter 3, we will explore the power of streams
further and look into exactly what those optimizations are.
Listing 1-13. Using streams for processing database results
funConnection.queryToStream("/* SQL HERE */")
.filter(it -> it.get("firstName").equals("Robert"))
.collectors(Collectors.summarizingInt(it -> it.getSalary()));
Is Java 8 a Functional Programming Language?
Now that Java is borrowing such a powerful feature from functional programming, does that make Java a
functional programming language? Many developers that I talk to have “Learn a functional programming
language” on their bucket list, 15 so does learning to code in idiomatic Java 8 count as learning a functional
Martin Odersky, the creator of Scala, weighed in on what made a “functional programming language.” 16
With the introduction of Java 8, Java now has all those features in an obvious way. Yet, just as Martin
pointed out about Scala, idiomatic Java 8 still does not strongly resemble idiomatic code in the functional
programming languages. 17 The term Martin coined to describe this kind of language is “postfunctional,”
which works well enough: Java 8 brings Java into the ranks of the postfunctional languages.
Part of the difficulty when talking about “functional programming” is that it's a strategy for
programming. Some languages more naturally express this strategy than others, but it is possible to do
functional programming in any language, just as it is possible to do object-oriented programming in any
language. 18 This means that we have been able to do functional programming in Java all along.
In fact, many of the innovations that have entered the Java ecosystem are actually functional
programming maneuvers in an object-oriented guise. This is exactly what we are seeing with our inversion-
of-control example: those interface implementations providing callbacks to JdbcTemplate are actually just an
object-oriented way of passing in a function. All JdbcTemplate wants is that function. In the object-oriented
world, we needed to create a structure to support it; in the functional world, we can just pass the function in.
What lambdas enable us to do is to express these programming strategies using a more natural language.
17 E.g., Haskell, OCaml, Lisp.
18 If you would like to see object-oriented programming done in C, for instance, see the GMP library's C API.