In this commodity, nosotros will cover Functional Programming from a Java language perspective. We will see how the Functional Programming style has been introduced starting from Java 8.

Effigy: Functional Programming in Coffee

Introduction

Contempo years we often hear the term Functional Programming in IT conferences or co-working space meetups. For developers who come from a solid informatics background, this is not new at all. In fact, it is the subset of two programming paradigms: imperative and declarative.

Figure: Programming linguistic communication paradigms

Information technology is of import to understand differences between imperative and declarative programming to come across why Functional Programming is now being widely adopted. Hither is a quick summary:

Characteristic Imperative Declarative
Programming Mode Focus on How: perform step-past-step tasks and manage changes in state Focus on What: define what the problem is and what data transformation is needed to achieve the solution
State Changes Stateful Stateless
Order of execution Statements are executed in a specific gild Statements can be executed in any club
Flow control Loops, conditionals, and function calls Function phone call and Recursion
Element Class objects and methods Functions, data sets

What is Functional Programming?

In Object Oriented Programming (OOP), the edifice block is a class, and every class extends from the Object grade. Nosotros encapsulate the states and behaviors of existent-world matter inside a class equally attributes and methods. On the other hand, in the about simplified definition, Functional Programming focusses on the part as the building block. Strictly speaking, fully supported Functional Programming must allow certain blueprint patterns:

  • Inferred blazon system
  • Support anonymous function
  • Implement Lambda calculus
  • Deferred execution
  • Immutable data structures
  • Non-strict, lazy evaluation

We will come across more details of how Java supports these features afterwards in this post.

If we follow the strict definition of Functional Programming, then Java (being a stiff object oriented language) is not a Functional Programming language. However, we notwithstanding tin can be benefit from writing effective functional-style programs in Java.

From version eight onward, Java has gradually added Functional Programming features to its capabilities. Starting with Lambda, in that location is a new style of using lambda expressions with Collection APIs and data processing with the new Stream API. In Java 10, Oracle introduced a long requested functional feature: "inferred blazon".

Why Functional Programming became famous again?

With improvement in compilers and increasing need for stateless programming models, software engineers have recently re-visited Functional Programming and invested more into it. In addition, the painful experience of maintaining multi-threaded OOP programs also pushes software engineers toward Functional Programming.

To demonstrate the popularity of Functional Programming in recent years, we can refer to the pinnacle 10 trending programming languages by IEEE:

screenshot of the the top ten list from the app
Trending programming languages (IEEE, 2019)

Hither we visit some of the languages in the top 10 in depth:

Programming language Description Applications
Python An interpreted, high level, full general-purpose programming language.  Typing subject: Duck, dynamic, gradual  Paradigm: Multi-image, functional, imperative, object-oriented, reflective - Artificial intelligence - embedded microcontrollers
C++ A loftier level, general purpose programming language.  Typing subject: Static, nominative  Paradigm: object oriented, functional - Software infrastructure and resource constrained applications. - Performance-critical applications
Coffee A general purpose, class based, object-oriented language.  Typing discipline: Static, strong  Image: multi-paradigm, object oriented, imperative, reflective Client-server web applications
JavaScript A programming language that conforms to the ECMAScript specification.  Typing discipline: Dynamic, duck  Image: Event-driven, functional, imperative Nearly all modern spider web applications crave JavaScript

We can meet that (without counting Java), many other languages have "Functional" in their paradigm style.

Volition the rise of Functional Programming impale OOP?

Java developers love Java and its OOP features. It's 4 key OOP features are embedded from the fourth dimension of studying in University through to a career as Java developer: Abstraction, encapsulation, inheritance and polymorphism. Explaining and using them is frequently deep in a programmer'southward comfort zone. Notwithstanding, every bit explained above, the benefits of Functional Programming are undeniable. Information technology was inevitable that Java would adopt Functional Programming, and that is exactly what Oracle had in mind with the introduction of Lambda and Stream support starting with Java 8.

Looking back to the peak 10 programming languages by IEEE, most offer multi-image support. They accept features for both OOP and Functional Programming. There is no "silver bullet" in the programming paradigm arroyo - some problems are better solved with OOP and some with Functional Programming. Here is a listing the Pros and Cons of OOP vs Functional:

OOP Functional
Usage Should be used when there are many things with few operations Should be used when there are few things with many operations
Execution State can exist changed thus unpredictable, peculiarly in race condition Information is immutable thus predictable
Modeling Inheritance and generics make information technology easier for modelling, code reusability and testability Limited
Lawmaking readability - Somewhat less verbose - Low level of code instruction; statements specify How - Concise: It takes fewer lines of code which in turn makes information technology easier to maintain - Free of low-level operations, and less error prone: specify What, and input are immutable
Performance Relies on multi-thread programming to use multi-core CPUs but leads to race condition problems. Developers must program carefully with synchronize block, notify, and lock mechanisms which are mistake prone. Low readability makes it difficult to maintain or debug Depends on libraries to leverage parallelism to heave performance.

How Coffee adapt to Functional Programming?

Java 8 introduced Functional Programming features with lambdas and streams. Let's wait at them in detail.

Lambda

Lambda expressions can be understood every bit a curtailed representation of an anonymous part that tin can be passed around (2015, Java eight in Action, Manning):

  • Bearding: information technology does not take an explicit proper noun like a method would
  • Office: Lambda expression is not associated with any class
  • Passed around: a lambda expression tin exist passed as argument to a method or stored in a variable
  • Concise: no more boilerplate code such equally variable declaration

Imagine that nosotros take a shopping cart checkout awarding where some products have a promotional discounts while others do non. The discounts can be dissimilar percentages. How can the total price of the shopping cart be calculated?

Using the old method:

          BigDecimal total = BigDecimal.Zero;  for(Product product: shoppingCart.products) {      if(production.hasPromotion == truthful)          full += production.price * production.promotion;  }                  

Using the new method:

          BigDecimal total = shoppingCart.products          .filter(prod -> prod.hasPromotion)          .map(prod -> prod.price * prod.promotion)          .reduce(BigDecimal.Cipher, BigDecimal::Add together);                  

Using Collection API with Lambda expressions

Prior to Java 8, the Collections API was ofttimes used with a loop control to iterate through the collection. Using this shopping cart example, how can all product inside the shopping cart be printed?

The old way:

          for(Production prod : shoppingCart.getAllProducts()) {      System.out.println(prod.getName());  }                  

The new style:

          shoppingCard.getAllProducts().foreach(Arrangement.out::println);                  

The new style is much more readable and concise as the Lambda expression helps us concisely iterate through a drove.

Another benefit of using a Functional Programming way in Java is that the side effect of a mutable input can exist avoided. For example, to get a List of all uppercase Product Names in shopping cart, there are ii choices.

The old way:

          List<Cord> uppercaseProdNames = new ArrayList<>();  for(Production prod : shoppingCart.products) {      uppercaseProdNames.add(prod.getName().toUpperCase());  }                  

The problem with this approach is that there is a possibility that the original shoppingCart products may be modified during the iteration. With a Lambda expression, we tin use its immutability characteristic to eliminate unpredicted behaviors such every bit modifying the original input.

The new way:

          List<String> uppercaseProdNames = shoppingCart.products      .stream()      .map(p -> p.getName().toUpperCase())      .collect(Collectors.toList());                  

Data processing using new Stream API

The above example uses the stream function of the Collection API. The Algorithm and Information Construction are the two almost of import subjects in informatics, and the Drove API is therefore used heavily by Java Developers. With the introduction of Functional Programming in Java with Lambda, Stream is the update necessary to manipulate Collections API in a functional manner. It also helps improve performance by leveraging parallelism without having to explicitly plan multi-threading. For example, this code snippet shows how a wheel store application can return listing of all bikes with a cost greater than $1500, sorted by toll descending.

The old way:

          Listing<Wheel> expensiveBikes = new ArrayList<>();  for(Bike bike: allBikes) {      if(cycle.getPrice() > 1500) {          expensiveBikes.add(bike);      }  }    // Sorting the expensiveBikes list in descending society  Collections.sort(expensiveBikes, new Comparator<Wheel>() {      public int compare(Bike b1, Bike b2) {          render Integer.compare(b2.getPrice(), b1.getPrice));      }  });    // Processing the sorted list to select titles of the bikes  List<String> expensiveBikeTitles = new ArrayList<>();  for(Bicycle wheel: expensiveBikes) {      expensiveBikeTitles.add together(bike.getTitle());  }                  

This code has some bug, including:

  • The introducing of the intermediate garbage variable expensiveBikes
  • Too many imperative lines of code that arrive difficult to follow the logic
  • Sequential loop makes it hard to introduce concurrent processing to ameliorate performance

To address these problems, in Java viii nosotros can write:

          List<String> expensiveBikeTitles = allBikes.parallelStream()          .filter(b -> b.getPrice() > 1500)          .sorted(comparing(Bicycle::getPrice))          .map(Wheel::getTitle)          .collect(Collectors.toList());                  

The code is much more than curtailed, existence written as a problem definition!

What's Next for Java Developer

The introduction of Lambda 8 and modifications to the Collection API with Stream were big changes to the Coffee programming language. Since then, Java has had multi-paradigm support for both OOP and Functional Programming, and Oracle has pushed information technology further in version 10 with introduction of the inferred blazon for local variables.

Java Developers can fifty-fifty explore Functional Programming with other languages.

Scala

Scala is a programming language that offers both Object-Oriented and Functional Programming. It is created for developer who has background in Java and desire to pursue more of Functional Programming. Scala programs run on a JVM and can likewise use Java libraries.

Kotlin

Similar Scala, Kotlin has both Object-Oriented and Functional features. Kotlin is also targeted for JVMs and can also utilise Coffee libraries. But it takes Functional Programming support even further with college-club functions. A higher-order office is a function that takes functions every bit parameters.

Bang-up

Coffee Developers tin too choose to piece of work with Groovy, another language that supports both OOP and Functional Programming. Apart from being more functional than Java, Groovy also differs from Java in that it supports the dynamic typing discipline.

Conclusion

While Java has adopted Functional-mode programming past introducing Lambda, OOP will not be abandoned from Coffee 8. Knowing pros and cons of both OOP and Functional, developers can mix both styles effectively. The real work object tin can be modelled with its states and their relationships leveraging Functional Programming for operations to improve code readability and performance. With its multi-epitome support, Java remains a great option for developing applications.