
That was the release of Java 8. Someone was really waiting for her and testing the pre-release version, counting the weeks to March, for someone changing the numbers in the JDK version was just a reason to play with the updated language a couple of times at home IDE (input of the language in production always takes some time), someone just doesn’t need new features, they lack the capabilities of the "seven" with interest. Nevertheless, it was worth waiting for the eighth Java - and not just waiting, but also looking closely at some of its innovations, because in this version there are actually quite a few of them, and if you take a closer look at them, it is possible that the well-known language will appear before you in completely new light, having pleased with the opportunity to write even more beautiful and concise code. And if we talk about the new features of Java 8, it would be strange not to start with lambda expressions.
It just so happened that in recent years, Oracle was difficult to “blame” for the rapid or revolutionary development of the language - while competitors in the shop were overgrown with new features almost every year, Java was slowly fixes bugs and rolled out essentials, sometimes - with some delay. So it was with lambda expressions. Rumors about them went even before the seventh version, but didn’t grow together, it was not only the crutches that partially solved this problem, then many found for themselves “Java with functionalism” in the form of Scala and more or less calmed down, then Java 8 a couple of times postponed - and now, finally, everyone who waited for the official support of the lambda.
')
Nevertheless, despite a certain interest in the topic among developers, many still do not quite understand why it is needed, how to use it, and what kind of functional programming is this, which still strives to step on the heels of other paradigms. Since each of these questions deserves at least a solid article (rather, even a book), in this post we will consider only some aspects of the use of lambda expressions in practice, using the simplest and most understandable examples. It should immediately warn dear readers that first of all this post was written in order to interest Java developers in the topic of lambdas in the new version of the language (if for some reason they did not know about them or did not appreciate them), without blowing up its at the expense of details and not scaring them at this stage in abstruse terms of functionalism. Therefore, if you already have experience with the functional paradigm, then most likely you will not find almost anything new in this article. All the rest, especially Java-developers, who taught Java a couple of versions back in its original version (without functional “crutches” like lambdaj), will probably be interesting.
Wean write a lot
Easier, probably, and can not be - create a list of numbers and display it on the screen through a simple loop:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6); for (int number : numbers) { System.out.println(number); }
Every person who used Java, probably wrote such cycles - it would seem impossible to invent something simpler and more convenient. Or is it possible? What happens in the loop? We all know the answer - the numbers are displayed one by one until the end of the list is reached. It sounds quite logical and correct, right? But let's look at the problem from the other side. A comparison comes to mind with a person who folds parts from the Lego designer scattered across the floor in one box - his cycle is that he takes one piece, puts it in a box, looks to see if there are any other details left on the floor. (there are not one hundred of them there), puts the next part in the box, checks again if there are no more parts left, puts it again, checks it again. But what prevents to take in the armful as many details as you can grab, and at once throw them in the box?
Let's try to move away from old habits and finally use lambdas. Here’s how the same code might look like in Java 8:
numbers.forEach((Integer value) -> System.out.println(value));
As we can see, the structure of a lambda expression can be divided into two parts: the part to the left of the arrow (->) contains the parameters of the expression, and the part to the right contains its body. The compiler already knows how to work with this expression, moreover - in most cases, the types in the lambda expressions can not be specified in the code explicitly, making the expression even more concise:
numbers.forEach(value -> System.out.println(value));
But this is not the limit - you can use the operator :: and get even more beautiful:
numbers.forEach(System.out::println);
I don’t know about you, but after that I don’t want to write cycles “in the old manner” at work after that.
Copy-paste or abstraction? Choose you!
But, of course, there would not be so much noise around the functional paradigm if it were needed only to display several numbers on the screen with a single line of code. If you at least briefly think about their application, then it turns out that it is also a matter of increasing the level of abstraction and flexibility of your projects. Let's take another example:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
Already familiar to us is a list, but now imagine that for a project (your own or a worker) you need to write a method that finds the sum of all the elements of the list (Oh, if the tasks were really so simple!)
public int sumAll(List<Integer> numbers) { int total = 0; for (int number : numbers) { total += number; } return total; }
Simply? Of course. Well, imagine, it took some time, and it turned out that you need to write another method - let it, for example, add only even numbers. Also a 10th grade level task, isn't it?
public int sumAllEven(List<Integer> numbers) { int total = 0; for (int number : numbers) { if (number % 2 == 0) { total += number; } } return total; }
Everything is fine, but the number of tasks is growing, and in one day we needed another method that finds the sum of all numbers greater than 3. I am sure that the first thing that comes up to the majority of developers is to single out the previous method, use the good old copy-paste and change the condition. Fine, the code works, but ... Is this the most logical approach? Imagine that new methods will have to be added all the time, and tomorrow we will need a method that counts sums of odd numbers, numbers greater than 2, less than 5, and so on. As a result, even school-level tasks will grow into a whole “sheet” of code. Is there really no simpler approach in 2014?
It would be strange if it was not. Let's use another feature of Java 8 - the Predicate functional interface, which defines
how we will sort our numbers
before summing them up.
public int sumAll(List<Integer> numbers, Predicate<Integer> p) { int total = 0; for (int number : numbers) { if (p.test(number)) { total += number; } } return total; }
In this case, the very implementation of all possible options, we can fit just 3 lines:
sumAll(numbers, n -> true); sumAll(numbers, n -> n % 2 == 0); sumAll(numbers, n -> n > 3);
Beauty is the same! And this can be seen only in two simple examples - without going deep into the wilds, without affecting the lazy evaluation and other important aspects. However, the purpose of this article was to interest Java developers in the topic of lambdas in the new version of the language (if for some reason they hadn’t paid attention to them before this point) without overloading the reader at this stage with hardware and all the depths of the ideas of AF.
If these practical examples inspire someone to find books and blogs on the topic, starting the way to comprehend Zen of functional programming (the way, of course, is not the shortest, but it’s such a beauty that requires sacrifices), then it will be very it is good - both for you and for me, because it turns out that it was not for nothing that I wrote. In addition, I am sure, in this way you will eventually find more successful examples that look
much more curious than those presented in this post. Thanks for attention!
Upd: in the comments suggested some interesting links on the topic.
winterbe.com/posts/2014/03/16/java-8-tutorial - A more detailed tutorial on Java 8 innovations.
java.dzone.com/articles/why-we-need-lambda-expressions - Examples of the use of lambda in Java in several parts.
docs.oracle.com/javase/tutorial/collections/streams/reduction.html - Use reduce (as alternatives for the last example from a post).