Java IoT Authors: Yeshim Deniz, Pat Romanski, Liz McMillan, Zakia Bouachraoui, Carmen Gonzalez

Related Topics: Java IoT

Java IoT: Article

The Rise of Functional Java Programming

Better living without side effects

This sum example we started with may be simple, but it already illustrates how functional programming is different. The obvious way to code this in Java would have been to initialize a counter to zero, iterate through the list, and keep modifying the counter by adding the next value. If you’ve been writing Java code for a long time, you may not realize how deeply ingrained it is for us to solve problems by constantly modifying variables, calling methods that modify objects, and so on. But in functional programming, your first instinct should be to think of every problem in terms of computing an output directly from an input, breaking it into smaller problems that you solve recursively if necessary.

Let’s come back to our original problem now and try to apply these concepts.

Rewriting Our Original Example
First let’s consider the Reader interface we started with:

public interface Reader {
  String read();

The idea of this interface is to provide access to a list of strings one at a time, presumably so we can do something to those strings. But the fundamental idea of this interface is not in keeping with functional programming, since every time you call read you change the state of the object. Can we come up with a more functional way of doing the same thing? Indeed we can, by changing the responsibilities slightly. Instead of feeding strings to a consumer one at a time, we will instead ask the consumer to tell us what work they want done on each string (using a callback) then we will do it to all of the strings. In Scala the equivalent to a Java interface is a trait, so our revised example will look like this:

trait Reader {
  def repeatForEach (f: String => Unit) = ()

We are replacing the read method with one called repeatForEach, which takes a callback as an argument. The callback must take a string as input and return nothing as output (that’s what the Unit type means in Scala), the idea being that repeatForEach will invoke the callback for each individual string. We say = () to declare that by default, this method does nothing. Now we need an equivalent to the ArrayReader that takes a list of strings at construction time, and can be used later to provide one-at-a-time access to those strings. In Scala you don’t implement an interface, you extend a trait. Furthermore, although Scala supports an Array type, we want to use the List type, which is immutable and emphasizes our functional style. So we end up with this:

class ArrayReader (strings : List[String]) extends Reader {
  override def repeatForEach (f: String => Unit) = {
    strings.foreach (f);

This defines a class ArrayReader that extends the Reader trait and that requires a list of Strings upon construction. Note that in Scala you can specify arguments in a class definition (almost like a function definition). This means that the arguments must be provided in every use of the constructor and they automatically become available as immutable class members. Thus the following code in Scala:

class ArrayReader (strings : List[String]) {

is analogous to the following Java code:

public class ArrayReader {

  private final List<String> strings;

  public ArrayReader (List<String> strings) {
    this.strings = strings;

Once you have an instance of the Scala ArrayReader class, at any point in the future you can call repeatForEach and pass it a callback, and it will perform the callback on each of the strings in the original list, in sequence. This is equivalent in usefulness to our original ArrayReader class. For example, here is how you would print out all of the strings:

object Main {
    def main(args: Array[String]) {
           val arrayReader: Reader = new ArrayReader(List(“Foo”, “Bar”, “Baz”));
        arrayReader.repeatForEach (println);

Now let’s write the CharReader class. It requires a Reader upon construction, and provides character-by-character access to all of the items in that reader:

class CharReader (r: Reader) extends Reader {
  override def repeatForEach (f: String => Unit) = {
    r.repeatForEach ((s: String) =>
        s.toList.foreach ((c: Char) =>
            f (c.toString)));

This is more difficult to understand, so let’s work through it step-by-step. The CharReader takes any kind of Reader as an argument upon construction, and is also a Reader itself – just like in our original example. Like the ArrayReader it provides a repeatForEach method that takes a callback argument. Whenever this method is called with a callback argument f, the CharReader calls repeatForEach on its underlying reader, providing its own callback, which calls toList.foreach on each String, allowing each character to be processed individually. The callback f is invoked on each character after converting it to a one-character string.

Scala supports type inference, meaning that you can omit many of the type declarations without sacrificing any type safety at all. Thus you can write this more compactly this way:

class CharReader (r: Reader) extends Reader {
  override def repeatForEach (f: String => Unit) = {
    r.repeatForEach (s => s.toList.foreach (c => f (c.toString)));

Now let’s try using our new classes:

object Main {

    def main(args: Array[String]) {

           val arrayReader: Reader = new ArrayReader(List(“Foo”, “Bar”, “Baz”));
        val charReader: Reader = new CharReader (arrayReader);

        arrayReader.repeatForEach (println);
        charReader.repeatForEach (println);

Here’s the output:


This looks surprisingly like our original example, doesn’t it? We have a Reader interface with ArrayReader and CharReader implementations with roughly the same meanings as in the corresponding Java versions. The only difference is that this example has no mutable state whatsoever. There is no point at which any variable is modified from an old value to a new value. Although state is still shared between the arrayReader and charReader objects (the charReader contains a reference to the arrayReader), it’s simply not possible for them to interact inappropriately. Whenever you call:

arrayReader.repeatForEach (...)

a given input of ... will always produce exactly the same result. There isn’t any method for resetting the iterator either, because there’s no such concept in this design. You can call arrayReader.repeatForEach as many times as you like, and each time it will iterate through the entire list with no possibility of problems occurring. It can be used in a multithreaded environment and race conditions won’t even be possible. Race conditions can only occur when you have mutable state.

It may seem like cheating to convert the program to a functional one by changing the design to use callbacks, but we argue that it’s fair game. Functional programming is all about programming without side effects (i.e., mutating state), and that means coming up with new idioms for solving familiar problems. In this case, the original iterator-based solution was very typical Java code. To achieve the same thing without side effects we had to pass callbacks around (also known as closures, function objects, or anonymous functions) but this is very typical in functional languages, which typically provide a clean, elegant syntax to support that style of programming.

Functional Programming in Java
Let’s explore how we can introduce functional programming concepts into our Java code, in case our managers are not yet ready to allow the use of Scala for commercial software development. Unfortunately Java lacks many advanced functional programming features and its syntax is not ideal for this. Higher order functions (i.e., functions that operate on other functions) are almost impossible to express, especially if you want to make them strongly typed. (Defining strongly typed higher order functions requires the use of generics and Java’s “type erasure” implementation of generics throws away a significant amount of type information at runtime in the interest of efficiency. Martin Odersky giveth and Martin Odersky taketh away.)

That being said, the recent support in Java for anonymous classes still allows us to represent our Scala Reader example reasonably faithfully in Java.

The reader example is revisited on Listing 2.

This Java solution is written in a functional style, although it may look awkward to most Java programmers. We had to introduce a StringCallback interface to represent the callback, and used the new anonymous class capability in several places. However this solution has all the virtues of the Scala solution. It is immune to the problems associated with shared mutable state, and can be used safely in a multithreaded environment without any need for locking or any risk of race conditions.

Not all functional programming idioms can be translated into Java, but some of the simpler ones can, and although they may seem unnatural at first, they do bring benefits. It’s always worth asking the question: Can I solve this problem without the use of mutable state?

A Reconciliation Example
Say you have two lists of information that have to be reconciled. You want to know which items are in one list and not in the other, and vice versa. This kind of problem sometimes crops up in financial applications, and is often solved by traversing both lists and building a data structure to store the differences (e.g., a hash table). A more functional solution to the problem is to write code that can subtract the contents of one list from another as shown in Listing 3.

This example shows a functional approach to reconciling lists of information, but also shows the kind of compromise that has to be made when doing this style of programming in Java. Unfortunately the built-in Java Collection classes do not efficiently support immutable lists, so there is no way in the diff function to build up the result without either using mutation or creating our own immutable collection classes. We chose a practical approach: Create a fresh LinkedList object when the recursion bottoms out then mutate it repeatedly by calling addFirst to build up the result. Although this is not functional, we are doing it in only one place, and we are changing an object that was created within the diff method, is never shared, and has no permanent state after the initial call returns. So the implementation of diff is “mostly functional,” and the rest of the example is completely functional. This solution has most of the virtues of functional programming in terms of avoiding the problems of shared mutable state, and doesn’t destroy its input lists the way the removeAll method would (as defined in the Java Collection classes).

A Tree Aggregation Example
Say you have a tree of any type of object. Let’s keep it simple and represent the tree as an array of Java objects, each element of which could be a leaf node or another array. You might want to calculate a value based on all elements of the tree. A functional approach to this problem is to define a TreeWalker that can traverse any tree and accept a user-provided aggregation function (see Listing 4).

Once again we rely on Java’s new anonymous class capability, but we avoid the use of generics because Java’s “type erasure” implementation of generics would not allow us to use instanceof.

In this example we created a tree of numbers called myTree with eight nodes. Then we used the TreeWalker twice, each time passing it a different aggregation rule; one that knows how to aggregate a tree by adding, and another that knows how to aggregate a tree by multiplying.

The point is that tree traversal and aggregation have been factored into a general-purpose capability, and complex operations can be performed on the tree without any need for mutable state. As in the previous example, there is brief use of mutable state in the implementation of the aggregate function, but it’s on a locally created unshared object, so it’s acceptable. Programming languages like Scala that are designed for functional programming would not even require that, since they support immutable collections.

The use of mutable state makes programs hard to understand, especially in conjunction with currently popular programming practices in which objects are created indirectly and state sharing is not obvious from reading the code. Furthermore in multithreaded environments, programs relying on mutable state are prone to race conditions, requiring the use of locking that can impact performance and make programs even harder to understand and debug.

Functional programming offers an alternative approach to solving computing problems based on transforming inputs into outputs in a stateless way. Functional programs are referentially transparent, meaning function calls can always be substituted with their results without changing the meaning of the program. The loss of expressive power from having to avoid the use of mutable state is compensated for by providing better support for manipulating function objects and combining them in useful ways.

You can start using rudimentary functional programming techniques in Java immediately, but advanced techniques require better programming language support than Java offers. Scala is a useful language for Java programmers to explore, as it provides excellent support for functional programming while fitting smoothly into the Java developer’s world.   

Additional Reading

More Stories By Joe Morrison

Joe Morrison is a managing consultant at Lab49, and has over 20 years of experience leading engineering teams in designing and building complex network-based applications. His projects have ranged from distributed object research at Verizon Laboratories, to value chain management software at Benchmarking Partners in Boston, to in-the-trenches SOA projects for financial services firms in New York. Joe holds a BMath degree in computer science from the University of Waterloo, and a master's degree in computer science from MIT. He is a regular blogger on http://blog.lab49.com/.

More Stories By Kalani Thielen

Kalani Thielen is a Lab49 technology consultant, working in the financial services industry. Prior to joining Lab49 in 2006, he worked for six years developing products for the publishing, advertising, and communications industries. As a specialist in programming language theory, his present work focuses on the development and certification of compilers for bond pricing and trading languages.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.

IoT & Smart Cities Stories
Dion Hinchcliffe is an internationally recognized digital expert, bestselling book author, frequent keynote speaker, analyst, futurist, and transformation expert based in Washington, DC. He is currently Chief Strategy Officer at the industry-leading digital strategy and online community solutions firm, 7Summits.
Digital Transformation is much more than a buzzword. The radical shift to digital mechanisms for almost every process is evident across all industries and verticals. This is often especially true in financial services, where the legacy environment is many times unable to keep up with the rapidly shifting demands of the consumer. The constant pressure to provide complete, omnichannel delivery of customer-facing solutions to meet both regulatory and customer demands is putting enormous pressure on...
IoT is rapidly becoming mainstream as more and more investments are made into the platforms and technology. As this movement continues to expand and gain momentum it creates a massive wall of noise that can be difficult to sift through. Unfortunately, this inevitably makes IoT less approachable for people to get started with and can hamper efforts to integrate this key technology into your own portfolio. There are so many connected products already in place today with many hundreds more on the h...
The standardization of container runtimes and images has sparked the creation of an almost overwhelming number of new open source projects that build on and otherwise work with these specifications. Of course, there's Kubernetes, which orchestrates and manages collections of containers. It was one of the first and best-known examples of projects that make containers truly useful for production use. However, more recently, the container ecosystem has truly exploded. A service mesh like Istio addr...
Digital Transformation: Preparing Cloud & IoT Security for the Age of Artificial Intelligence. As automation and artificial intelligence (AI) power solution development and delivery, many businesses need to build backend cloud capabilities. Well-poised organizations, marketing smart devices with AI and BlockChain capabilities prepare to refine compliance and regulatory capabilities in 2018. Volumes of health, financial, technical and privacy data, along with tightening compliance requirements by...
Charles Araujo is an industry analyst, internationally recognized authority on the Digital Enterprise and author of The Quantum Age of IT: Why Everything You Know About IT is About to Change. As Principal Analyst with Intellyx, he writes, speaks and advises organizations on how to navigate through this time of disruption. He is also the founder of The Institute for Digital Transformation and a sought after keynote speaker. He has been a regular contributor to both InformationWeek and CIO Insight...
Andrew Keys is Co-Founder of ConsenSys Enterprise. He comes to ConsenSys Enterprise with capital markets, technology and entrepreneurial experience. Previously, he worked for UBS investment bank in equities analysis. Later, he was responsible for the creation and distribution of life settlement products to hedge funds and investment banks. After, he co-founded a revenue cycle management company where he learned about Bitcoin and eventually Ethereal. Andrew's role at ConsenSys Enterprise is a mul...
To Really Work for Enterprises, MultiCloud Adoption Requires Far Better and Inclusive Cloud Monitoring and Cost Management … But How? Overwhelmingly, even as enterprises have adopted cloud computing and are expanding to multi-cloud computing, IT leaders remain concerned about how to monitor, manage and control costs across hybrid and multi-cloud deployments. It’s clear that traditional IT monitoring and management approaches, designed after all for on-premises data centers, are falling short in ...
In his general session at 19th Cloud Expo, Manish Dixit, VP of Product and Engineering at Dice, discussed how Dice leverages data insights and tools to help both tech professionals and recruiters better understand how skills relate to each other and which skills are in high demand using interactive visualizations and salary indicator tools to maximize earning potential. Manish Dixit is VP of Product and Engineering at Dice. As the leader of the Product, Engineering and Data Sciences team at D...
Dynatrace is an application performance management software company with products for the information technology departments and digital business owners of medium and large businesses. Building the Future of Monitoring with Artificial Intelligence. Today we can collect lots and lots of performance data. We build beautiful dashboards and even have fancy query languages to access and transform the data. Still performance data is a secret language only a couple of people understand. The more busine...