📜 ⬆️ ⬇️

Functional programming in Java

This article is about:

If you are programming in Java, C #, C ++, PHP, or any other OO language, you would like to get acquainted with functional programming, but do not have the ability / desire to learn Haskell / Scala / Lisp / Python, this article is for you.

Those who are familiar with functional programming, but have never used it in Java, I think it will be interesting too.


Introduce the “function” construct in the Java language


What is functional programming? If in a nutshell, functional programming is programming, in which functions are objects, and they can be assigned to variables, passed as arguments to other functions, returned as a result from functions, etc. The advantages that such a possibility reveals will be clear later. For now, we need to figure out how in Java you can use the “function” construct itself.
')
As you know, in Java there are no functions, there are only classes, methods and objects of classes. But in Java there are anonymous classes, that is, classes with no name that can be declared directly in the code of any method. We will take advantage of this. First, let's declare such an interface:

public final interface Function<F, T> { T apply(F from); } 


Now in the code of some method we can declare an anonymous implementation of this interface:

 public static void main() { //  "",    intToString. Function<Integer, String> intToString = new Function<Integer, String>() { @Override public String apply(Integer from) { return from.toString(); } }; intToString.apply(9000); //   .   "9000". } 


We will call this implementation an “anonymous function”. From the point of view of functional programming, it is possible to do everything the same as with a function from functional languages: assign variables, pass as an argument to other functions (and class methods), receive as a result from functions (and class methods).

Now you can proceed to the presentation of some basic patterns of functional programming.

Working with collections in a functional style.


Suppose we have a certain collection of integers. We want to display them as a string, and each number in the string will be separated by a comma. A non-functional solution would look something like this:

 public String joinNumbers(Collection<? extends Integer> numbers) { StringBuilder result = new StringBuilder(); boolean first = true; for (Integer number : numbers) { if (first) first = false; else result.append(", "); result.append(number); } return result; } 


To implement a functional solution, we need to first prepare several functions and methods. We will declare them as static class fields:

 public static final Function<Integer, String> INT_TO_STRING = ... //    //      from,      transformer //         . public static <F, T> List<T> map(Collection<F> from, Function<? super F,? extends T> transformer) { ArrayList<T> result = new ArrayList<T>(); for (F element : from) result.add(transformer.apply(element)); return result; } //          public static <T> String join(Collection<T> from, String separator) { StringBuilder result = new StringBuilder(); boolean first = true; for (T element : from) { if (first) first = false; else result.append(separator); result.append(element); } return result.toString(); } 


Now our joinNumbers method will look like this:

 public String joinNumbers(Collection<? extends Integer> numbers) { return join(map(numbers, INT_TO_STRING), ", "); } 


The method is implemented in exactly one simple line.

I would like to note several important points:
  1. The map and join methods are fairly generalized, that is, they can be used not only to solve this problem. This means that they could be allocated to a utility class, and then use this class in different parts of the project.
  2. Instead of the Collection class in the map method, it would be possible to pass Iterable and return a new Iterable , retrieving data from the transferred collection as the data in the returned collection is crawled, that is, it is lazy to retrieve elements, step by step, and not all at once. Such an implementation will allow, for example, to create a chain of data conversion, highlighting each stage of the conversion into a separate simple function, while the efficiency of the algorithm will remain on the order of O (n):
    map(map(numbers, MULTIPLY_X_2), INT_TO_STRING); // .
  3. By creating a class, you can create static fields for some of its methods, which are wrapper functions that delegate the call to apply to a call to the corresponding class method. This will allow the use of “methods” of objects in a functional style, for example, in the structures presented above.


Working with collections using Google Collections



The guys from Google just created a convenient library with utility classes that allows you to work with collections in Java in a functional style. Here are some of the features that it provides:


Of course, there are many other useful things in Google Collections, both for functional programming and for working with collections in an imperative style.

Links



What I would like to tell more


Dear friends, if you like my article, I will gladly write something else interesting about the use of functional programming in Java and other imperative languages. Here are some of the things about which there is a desire to tell, but there is no possibility to present immediately in one article:
  1. Mutable and Immuntable Circuits.
  2. Pattern-matcher.
  3. Monads.
  4. Parallelization using a functional approach.
  5. Parser combinators.

I will be glad to hear your comments and suggestions.

Source: https://habr.com/ru/post/122919/


All Articles