Preface

A mind that is stretched by a new experience can never go back to its old dimensions.

Oliver Wendell Holmes Jr.


Developing software can be quite a complex endeavor. As Java developers, we usually try to tame this complexity with object-oriented programming (OOP) and an imperative coding style. But not every problem is a good match for an object-oriented coding style. We end up introducing even more complexity by not solving problems with the best tools and paradigms available to us. The functional programming (FP) paradigm offers another approach to solving problems.

After spending its early life hidden away in academia and niches, functional programming is on the rise again and becoming more mainstream. The ideas and concepts behind it are adopted in almost every multi-paradigm and general-purpose language, allowing us to use some form of functional programming regardless of the context. And it’s not a surprising trend.

New Hardware Needs a New Way of Thinking

Our hardware is evolving in a new direction. Moore’s law — coined in 1965 as the observation of transistor counts doubling every two years, and therefore the performance per core available to us — seems to slow down.1 For quite some time, single-core performance improvements are getting smaller with each processor generation. The manufacturers favor more cores — even specialized ones — over ever-increasing transistor count and clock rates per core.2 That’s why modern workloads need new ways to reap all the benefits such new hardware offers: parallelism.

Scaling your software horizontally through parallelism isn’t an easy task in OOP. Not every problem is a good fit for parallelism. More painters might paint a room faster, but you can’t speed up pregnancy by involving more people. If the problem consists of serial or interdependent tasks, concurrency is preferable to parallelism.

But if a problem can be broken down into smaller, non-related sub-problems, parallelism really shines. And the stateless and immutable nature of idiomatic FP provides all the tools necessary to build small, reusable tasks to be easily used in parallel environments. That’s just one of many benefits of a more functional approach to your daily development problems.

Why Java?

There are many programming languages to choose from when you want to start with functional programming. Haskell is a favorite if you prefer a pure functional language with almost no support for an imperative coding style. But you don’t have to leave the JVM ecosystem behind to find FP-capable languages. Scala shines in combining OOP and FP paradigms into a concise, high-level language. Another popular choice, Clojure, was designed as a functional language with a dynamic type system at heart. But sometimes, you won’t have the luxury of choosing the language for your project or problem, and you’ll have to play the cards you’re dealt, and you’ll need to use Java.

Even though you can implement most functional principles in Java regardless of deeply integrated language level support3, your code won’t be as concise and easy to reason with as it would in other languages. And without such support, many developers didn’t bother to embrace these principles, even if they could have provided a more productive approach or better overall solution.

In the past, many people thought of Java as a slow-moving behemoth, a “too big to become extinct” enterprise language, like a more modern version of COBOL or FORTRAN. And in my opinion, that’s partially true. The pace didn’t pick up until Java 9 and the shortened release timeframes4. It took Java five years to go from version 6 to 7 (2006-2011). And even though there were significant new features, like try-with-resources, none of them were “ground-breaking”. The few and slow changes in the past led to projects and developers not adopting the “latest and greatest” Java Development Kit (JDK), missing out on many language improvements. Three years later, in 2014, the next version, Java 8, was released. But this time, it introduced one of the most significant changes to Java’s future: lambda expressions.

A better foundation for functional programming had finally arrived in arguably the most prominent object-oriented programming language of the world, changing the language and its idioms significantly:

Runnable runnable = () -> System.out.println("hello, functional world!");

A whole new world of ideas and concepts was made available to Java developers by introducing lambda expressions. Many of the JDK’s new features, like Streams, or the Optional type, are only possible in such a concise way thanks to language-level lambda expressions. But the new idioms and way of doing things with FP might not come naturally, especially after spending so much time in an “object-oriented headspace”.

Why I Wrote This Book

After using a more functional style in other languages I work with, like Swift, I gradually introduced more functional principles in my Java-based projects. That led me to realize something: How to use lambdas, Streams, and other functional tools provided by Java, is easy to grasp. But without understanding why you should use them — and when not to — you won’t unlock their full potential, and it will just be “new wine in old wineskins.”

So I decided to write this book to highlight the different concepts that make a language functional, and how you can incorporate them into your Java code, either with the tools provided by the JDK or by creating them yourself. A functional approach to your Java code will most likely challenge the status quo and go against best practices you were using before. But by embracing a more functional way of doing things, like immutability and pure functions, you will be able to write more concise, more reasonable, and future-proof code that is less prone to bugs.

Who Should Read This Book

This book is for you if you are curious about functional programming and want to know what all the fuss is about and apply it to your Java code. You might already be using some functional Java types but desire a more profound knowledge of why and how to apply them more effectively.

There is no need to be an expert on OOP, but the book is not a beginner’s guide to Java or OOP. You should already be familiar with the Java standard library. No prior knowledge of functional programming is required. Every concept is introduced with an explanation and examples.

The book covers Java 17 as the latest Long-Term-Support (LTS) version available at publication. But knowing that many developers need to support projects with earlier versions, the baseline will be the previous LTS, Java 11.

This book might not be for you if you are looking for a compartmentalized, recipe-style book presenting “ready-to-implement” solutions. Its main intention is to introduce functional concepts and idioms and teach you how to incorporate them into your Java code.

What You Will Learn

By the end of this book, you will have a fundamental knowledge of functional programming and its underlying concepts and how to apply this knowledge to your daily work. Every Java functional type will be at your disposal, and you will be able to build anything missing from the JDK by yourself, if necessary.

A functional approach will lead to many advantages in your code:

  • Composition: Build modular and easy composable blocks.

  • Expressiveness: Write more concise code that clearly expresses its intent.

  • More reasonable code: Safer data structures without side-effects that don’t need to deal with locks or race conditions.

  • Modularity: Break down larger projects into more easily manageable modules.

  • Maintainability: Smaller functional blocks with less interconnection make changes and refactoring safer without breaking other parts of your code.

  • Data manipulation: Build efficient data manipulation pipelines with less complexity.

  • Performance: Immutability and predictability allow to scale horizontally with parallelism without much thought about it.

  • Testing: Verify your building blocks with ease.

Even without going fully functional, your code will benefit from the concepts and idioms presented in this book. And not only your Java code. You will tackle development challenges with a functional mindset, improving your programming regardless of the used language or paradigm.

What About Android?

Talking about Android in a Java context is always a challenging endeavor. Even though you can write Android applications in Java, the underlying API isn’t the same, and Android doesn’t run Java bytecode on a JVM. Instead, it recompiles the Java bytecode for its own runtime.

Android is (not) Java

Android chose Java as its primary language for multiple reasons. At the time of Android’s inception, Java was a well-known language and the first programming language many universities taught their students. Also, it offered a vast pool of developers and a vibrant ecosystem of compatible libraries. But instead of running Java bytecode on a minimalistic JVM, like Java Platform Micro Edition, the Java bytecode is recompiled. The Dex-compiler creates Dalvik bytecode, which runs on a specialized runtime: the Android Runtime (ART), and previously on the Dalvik virtual machine 5.

Recompiling Java bytecode to Dalvik bytecode allows the devices to run highly optimized code, getting the most out of their hardware constraints. But for you as a developer, that means that even though your code looks and feels like Java, and most of the public API is available to you, there isn’t a feature parity between the JDK and Android SDK you can rely on. For example, the cornerstones of this book — lambda expressions and streams — were among the missing features in Android for a long time.

Desugaring Android Java Code

The expression “syntactic sugar” describes features that are additions to a language’s syntax to make your life as a developer “sweeter”. It provides an alternative, more concise style for more complex tasks. You will learn more about in [Link to Come]. For example, augmented assignments, prefix and postfix operators, and type inference, as shown in Table P-1, are “syntactic sugar” you might already use.

Table P-1. Syntactic sugar

Description

With Sugar

Without Sugar

Type inference

var x = 42L;

long x = 42L;

Type inference

List<String> list = new ArrayList<>();

List<String> list = new ArrayList<String>();

Augmented Assignment

x += 1;

x = x + 1;

Postfix Operator

x++;

x = x + 1;

The compiler is responsible for removing the “sweetness” by desugaring your code, returning it to the actual form that gets compiled.

Java lambda expressions are more than just “syntactic sugar”, as you will learn more about in [Link to Come]. But for Android, there was no other option to support various Java 8+ features than desugaring. At least without implementing them natively at a runtime level. Starting with 3.0.0, the Android Gradle plugin supports automatic desugaring of the following features that are covered in this book:

  • Lambda expressions (without serialization support)

  • Method references

  • Default and static interface methods

The next major version, 4.0.0, added even more functional features:

  • Streams

  • Optionals

  • The java.util.function package

Keep in mind that even though all these features are finally available in Android, they are implemented differently from the JDK6.

A Functional Approach to Android

In 2019, Google announced that Java is no longer the preferred language for Android app developers. It got replaced by Kotlin, after making it an available option two years prior. Kotlin is a multi-platform language that mainly targets the JVM but also compiles to JavaScript and many multiple native platforms, too7. It aims to be a “modern and more concise” Java, fixing many of Java’s debatable shortcomings and cruft accumulated over the years due to backward compatibility, without forgoing all the available frameworks and libraries available in Java. It’s 100% interoperable with Java, and you can mix Java and Kotlin in the same project with ease.

One obvious advantage of Kotlin over Java is that many of the introduced functional concepts and idioms are an integral part of the language itself. But Kotlin has its own idioms and best practices that differ from Java’s. The generated bytecode might differ, too, like how to generate lambdas8. The most significant advantage of Kotlin is its attempt to create a more concise and predictable language compared to Java. And just like you can be more functional in Java without going fully functional, you can use Kotlin-only features without going full Kotlin in your Android projects. By mixing Java and Kotlin, you can pick the best features from both sides.

Keep in mind that this book’s primary focus is Java. Most of the ideas behind what you will learn are transferrable to Android, even if you use Kotlin. But there won’t be any special considerations for Android throughout the book.

Navigating This Book

This book consists of three different parts. Reading them in their respective order will let you get the most of them because they build on each other. The contained chapters, however, are only loosely coupled. So feel free to skim for the bits that might interest you and jump around. Any necessary connections are cross-referenced.

  • Part I, A Functional Approach, covers a high-level overview of functional programming and the types already available to Java developers to better understand the different concepts’ underlying philosophy. It’s followed by a topic-based deep-dive through the different concepts and how to use them.

  • In [Link to Come], Real-World Problems, Patterns and Recipes, you will see how to apply the previously learned knowledge to typical real-world problems you might encounter in your daily work.

Conventions Used in This Book

The following typographical conventions are used in this book:

Italic

Indicates new terms, URLs, email addresses, filenames, and file extensions.

Constant width

Used for program listings, as well as within paragraphs to refer to program elements such as variable or function names, databases, data types, environment variables, statements, and keywords.

Constant width bold

Shows commands or other text that should be typed literally by the user.

Constant width italic

Shows text that should be replaced with user-supplied values or by values determined by context.

Tip

This element signifies a tip or suggestion.

Note

This element signifies a general note.

Warning

This element indicates a warning or caution.

Using Code Examples

The source code for the book is available on GitHub: https://github.com/benweidig/a-functional-approach-to-java. Besides compilable Java code, there are also JShell scripts available to run the code more easily. See the README.md for instructions on how to use them.

Supplemental material (code examples, exercises, etc.) is available for download at https://github.com/oreillymedia/title_title.

If you have a technical question or a problem using the code examples, please send email to .

This book is here to help you get your job done. In general, if example code is offered with this book, you may use it in your programs and documentation. You do not need to contact us for permission unless you’re reproducing a significant portion of the code. For example, writing a program that uses several chunks of code from this book does not require permission. Selling or distributing examples from O’Reilly books does require permission. Answering a question by citing this book and quoting example code does not require permission. Incorporating a significant amount of example code from this book into your product’s documentation does require permission.

We appreciate, but generally do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN. For example: "Book Title by Some Author (O’Reilly). Copyright 2012 Some Copyright Holder, 978-0-596-xxxx-x.”

If you feel your use of code examples falls outside fair use or the permission given above, feel free to contact us at .

O’Reilly Online Learning

Note

For more than 40 years, O’Reilly Media has provided technology and business training, knowledge, and insight to help companies succeed.

Our unique network of experts and innovators share their knowledge and expertise through books, articles, and our online learning platform. O’Reilly’s online learning platform gives you on-demand access to live training courses, in-depth learning paths, interactive coding environments, and a vast collection of text and video from O’Reilly and 200+ other publishers. For more information, visit http://oreilly.com.

How to Contact Us

Please address comments and questions concerning this book to the publisher:

  • O’Reilly Media, Inc.
  • 1005 Gravenstein Highway North
  • Sebastopol, CA 95472
  • 800-998-9938 (in the United States or Canada)
  • 707-829-0515 (international or local)
  • 707-829-0104 (fax)

We have a web page for this book, where we list errata, examples, and any additional information. You can access this page at https://learning.oreilly.com/home/.

Email to comment or ask technical questions about this book.

For news and information about our books and courses, visit http://oreilly.com.

Find us on Facebook: http://facebook.com/oreilly

Follow us on Twitter: http://twitter.com/oreillymedia

Watch us on YouTube: http://www.youtube.com/oreillymedia

Acknowledgments

1 Edwards, Chris. 2021. “Moore’s Law: What Comes Next?” Communications of the ACM, February 2021, Vol. 64 No. 2, 12–14.

2 Thompson, N. C., and Svenja Spanuth. 2021. “The decline of computers as a general-purpose technology.” Communications of the ACM, Vol. 64, No. 3, 64-72.

3 Dean Wampler shows in his book “Functional Programming for Java Developers” quite detailed how to implement and facilitate the missing functional programming features in Java all by yourself. He showed many techniques that weren’t easily feasible before version 8. But now, many of the shortcomings and gaps in the JDK are closed up, and it provides many of the tools necessary to incorporate FP concisely and more straightforward.

4 Oracle introduced a faster release schedule for Java with the release of version 9. Instead of releasing infrequently, there’s now a fixed release cadence of six months. To meet such a tight schedule, not every release is considered “long-term-support”, in favor of releasing features faster than before.

5 The Android Open Source project provides a good overview of the features and the reasoning behind Android’s runtime.

6 Jack Wharton, a well-known Android developer, provides a detailed insight on how Android desugars modern Java code.

7 See the official Kotlin documentation for an overview of supported platforms.

8 Each lambda compiles to an anonymous class extending kotlin.jvm.internal.FunctionImpl, as explained in the function type specs.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.87.209.162