10 typical examples of Java 8 Lambda expressions

Source: Internet
Author: User
Tags stream api netbeans

10 typical examples of Java 8 Lambda expressions

Java 8 was released just a few weeks ago on July 15, March 18, 2014. This groundbreaking release aroused a lot of discussions in the Java Community and made everyone feel excited. One of the features is the lambda tabulation that is released along with it, which allows us to pass behavior to the function. Before Java 8, if you want to pass behavior into a function, you only need six lines of code to select an anonymous class. The line of code that defines the most important behavior is not highlighted in the middle. Lambda expressions replace anonymous classes, cancel templates, and allow code writing in functional styles. In this way, sometimes the readability is better and the expression is clearer. In the Java ecosystem, functional expression and full object-oriented support are an exciting step forward.

It will further promote the development of parallel third-party libraries and make full use of multi-core CPUs. Although the industry needs time to digest Java 8, I believe that any rigorous Java developers should not ignore the core features of this Java release, lambda expressions, functional interfaces, stream APIs, default methods, and new Date and Time APIs. As a developer, I found that the best way to learn and master lambda expressions is to be brave enough to practice lambda expression examples as much as possible. Since Java Collection framework Java Collections framework is the most affected by the release of Java 8), it is best to practice stream API and lambda expressions for Lists and Collections) data is extracted, filtered, and sorted. I have been writing about Java 8 and have shared some resources in the past to help you master Java 8. This article describes how to use the 10 most useful lambda expressions in the Code. These examples are short and concise and will help you quickly learn about lambda expressions.

Java 8 lambda expression example

I am very excited about the release of Java 8, especially lambda expressions and stream APIs. More and more people are learning about them. I can write more clean code. This was not the case at the beginning. When I saw the Java code written in lambda expressions for the first time, I was very disappointed with this mysterious syntax and thought that they made Java unreadable, but I was wrong. It took me a day to do some lambda expressions and stream API example exercises, and I was happy to see a clearer Java code. This is a bit like learning generics. I hate it the first time I saw it. I even continued to use the old version of Java 1.4 to process collections. I realized the benefits of using generics only one day when my friend introduced me ). Therefore, the basic principle is not to fear the mysterious syntax referenced by lambda expressions and methods. After several exercises are performed to extract and filter data from the Collection class, you will like it. Let's start learning Java 8 lambda expressions. First, let's start with a simple example.

Example 1: Use a lambda expression to implement Runnable

When I started using Java 8, I first replaced the Anonymous class with lambda expressions, and implementing the Runnable interface is the best example of the anonymous class. Let's take a look at the runnable implementation method before Java 8. Four lines of code are required, while only one line of code is required to use lambda expressions. What have we done here? That is, the entire Anonymous class is replaced by the code block ()->.

// Before Java 8:
New Thread (new Runnable (){
@ Override
Public void run (){
System. out. println ("Before Java8, too much code for too little to do ");
}
}). Start ();

// Java 8 Mode:
New Thread ()-> System. out. println ("In Java8, Lambda expression rocks !! "). Start ();

Output:

Too much code, for too little to do
Lambda expression rocks !!

This example shows the syntax of Java 8 lambda expressions. You can use lambda to write the following code:

(Params)-> expression
(Params)-> statement
(Params)-> {statements}

For example, if your method does not modify or override the parameters, but prints something on the console, you can write it like this:

()-> System. out. println ("Hello Lambda Expressions ");

If your method receives two parameters, you can write them as follows:

(Int even, int odd)-> even + odd

By the way, the internal variable names of lambda expressions are usually shortened. In this way, the code can be shorter and put on the same line. Therefore, in the above Code, selecting a, B, x, and y for variable names is better than even and odd.

Example 2: Use a Java 8 lambda expression for event processing

If you have used Swing API programming, you will remember how to write event listening code. This is also a classic case of simple anonymous classes in the old version, but now it is okay. You can use lambda expressions to write better event listening code, as shown below:

// Before Java 8:
JButton show = new JButton ("Show ");
Show. addActionListener (new ActionListener (){
@ Override
Public void actionreceivmed (ActionEvent e ){
System. out. println ("Event handling without lambda expression is boring ");
}
});

// Java 8 Mode:
Show. addActionListener (e)-> {
System. out. println ("Light, Camera, Action !! Lambda expressions Rocks ");
});

Java developers often use the Anonymous class. The other part is to customize the Comparator for Collections. sort. In Java 8, you can replace an ugly anonymous class with a more readable lambda expression. It is not difficult for me to leave this exercise. I can follow the routine in the process of using lambda expressions to implement Runnable and ActionListener.

Example 3: Use a lambda expression to iterate the list

If you have been using Java for a few years, you will know that for the Collection class, the most common operation is to iterate and apply the business logic to various elements, such as the list of processing orders, transactions, and events. Since Java is an imperative language, all loop code before Java 8 is ordered, that is, its elements can be processed in parallel. If you want to perform parallel filtering, you need to write your own code, which is not that easy. By introducing lambda expressions and default methods, we can separate the question of what to do and how to do it. This means that the Java set now knows how to do iteration, the Set elements can be concurrently processed at the API layer. In the following example, I will describe how to iterate the list with lambda or without lambda expressions. You can see that the list now has a forEach () method, which can iterate all objects and apply your lambda code to them.

// Before Java 8:
List features = Arrays. asList ("Lambdas", "Default Method", "Stream API", "Date and Time API ");
For (String feature: features ){
System. out. println (feature );
}

// After Java 8:
List features = Arrays. asList ("Lambdas", "Default Method", "Stream API", "Date and Time API ");
Features. forEach (n-> System. out. println (n ));

// It is more convenient to use the Java 8 method reference. The method reference is indicated by the: Double colon operator,
// It looks like the scope parsing operator of C ++
Features. forEach (System. out: println );

Output:

Lambdas
Default Method
Stream API
Date and Time API

The last example of a list loop shows how to use method reference in Java 8 ). You can see that the double colons and range resolution operators in C ++ are now used in Java 8 to indicate method references.

Example 4: Use lambda expressions and functional interfaces Predicate

In addition to supporting functional programming style at the language level, Java 8 also adds a package called java. util. function. It contains many classes to support Java functional programming. One of them is Predicate. Using java. util. function. Predicate functional interfaces and lambda expressions, you can add logic to API methods and support more dynamic behaviors with less code. The following is an example of Java 8 Predicate, which shows a variety of common methods for filtering set data. The Predicate interface is very suitable for filtering.

Public static void main (args []) {
List languages ages = Arrays. asList ("Java", "Scala", "C ++", "Haskell", "Lisp ");

System. out. println ("ages which starts with J :");
Filter (ages, (str)-> str. startsWith ("J "));

System. out. println ("ages which ends with ");
Filter (ages, (str)-> str. endsWith (""));

System. out. println ("Print all ages :");
Filter (ages, (str)-> true );

System. out. println ("Print no language :");
Filter (ages, (str)-> false );

System. out. println ("Print language whose length greater than 4 :");
Filter (ages, (str)-> str. length ()> 4 );
}

Public static void filter (List names, Predicate condition ){
For (String name: names ){
If (condition. test (name )){
System. out. println (name + "");
}
}
}

Output:

Ages which starts with J:
Java
Ages which ends with
Java
Scala
Print all ages:
Java
Scala
C ++
Haskell
Lisp
Print no language:
Print language whose length greater than 4:
Scala
Haskell

// A better solution
Public static void filter (List names, Predicate condition ){
Names. stream (). filter (name)-> (condition. test (name). forEach (name)-> {
System. out. println (name + "");
});
}

As you can see, the Stream API filtering method also accepts a Predicate, which means that we can replace the custom filter () method with the Inline code written in it, which is the magic of lambda expressions. In addition, the Predicate interface also allows multiple conditions to be tested. The following example will be used.

Example 5: Add Predicate to lambda expressions

As mentioned in the previous example, java. util. function. Predicate allows two or more Predicate to be merged into one. It provides a method similar to the logical operators AND and OR, called AND (), or (), and xor (), used to combine conditions passed into the filter () method. For example, to obtain all languages with a length of four letters starting with J, you can define two independent Predicate examples to represent each condition, and then use Predicate. the and () method combines them as follows:

// You can even use and (), or (), and xor () logical functions to merge Predicate,
// For example, to find all the names starting with J with a four-letter length, you can combine two Predicate and Input
Predicate <String> startsWithJ = (n)-> n. startsWith ("J ");
Predicate <String> fourLetterLong = (n)-> n. length () = 4;
Names. stream ()
. Filter (startsWithJ. and (fourLetterLong ))
. ForEach (n)-> System. out. print ("nName, which starts with 'J' and four letter long is:" + n ));

Similarly, you can use the or () and xor () methods. This example focuses on the following points: You can use Predicate as a separate condition as needed and then combine it for use. In short, you can use the Predicate interface using traditional Java commands, or make full use of lambda expressions to get twice the result with half the effort.

Example 6. Map and Reduce using lambda expressions in Java 8

This example introduces the most widely known functional programming concept map. It allows you to convert objects. For example, in this example, we convert each element in the costBeforeTax list into a value after tax. We pass the x-> x * x lambda expression to the map () method, which applies it to every element in the stream. Then print the list elements using forEach. You can use the collector class of the stream API to get all the tax-included overhead. A method such as toList () combines the results of map or any other operation. Because the collector performs terminal operations on the stream, the stream cannot be reused later. You can even use the reduce () method of the stream API to merge all the numbers into one. The next example will show.

// Do not use lambda expressions to add a 12% tax to each order
List costBeforeTax = Arrays. asList (100,200,300,400,500 );
For (Integer cost: costBeforeTax ){
Double price = cost +. 12 * cost;
System. out. println (price );
}

// Use a lambda expression
List costBeforeTax = Arrays. asList (100,200,300,400,500 );
CostBeforeTax. stream (). map (cost)-> cost +. 12 * cost). forEach (System. out: println );

Output:

112.0
224.0
336.0
448.0
560.0
112.0
224.0
336.0
448.0
560.0

Examples of Map and Reduce using lambda expressions in Java 8, 6.2

In the previous example, we can see that map converts the elements of a collection class such as a list. Another reduce () function can combine all values into one. Map and Reduce operations are the core operations of functional programming. Because of their functions, reduce is also called a folding operation. In addition, reduce is not a new operation, and you may already use it. Aggregate functions similar to sum (), avg (), or count () in SQL are actually reduce operations because they receive multiple values and return one value. The performanceh () function defined by the stream API can accept lambda expressions and merge all values. Classes such as IntStream include built-in methods like average (), count (), sum () for reduce operations, and mapToLong () and mapToDouble () for conversion. This does not limit you. You can use the built-in method or define it yourself. In this Java 8 Map Reduce example, we first apply 12% VAT for all prices, and then use the reduce () method to calculate the sum.

// Add a 12% tax to each order
// Old method:
List costBeforeTax = Arrays. asList (100,200,300,400,500 );
Double total = 0;
For (Integer cost: costBeforeTax ){
Double price = cost +. 12 * cost;
Total = total + price;
}
System. out. println ("Total:" + total );

// New method:
List costBeforeTax = Arrays. asList (100,200,300,400,500 );
Double bill = costBeforeTax. stream (). map (cost)-> cost +. 12 * cost ). reduce (sum, cost)-> sum + cost ). get ();
System. out. println ("Total:" + bill );

Output:

Total: 1680.0
Total: 1680.0

Example 7: Create a String list by filtering

Filtering is a common operation for Java developers on a large-scale collection. Currently, using lambda expressions and stream APIs to filter large-scale data sets is incredibly simple. A stream provides a filter () method that accepts a Predicate object. That is, a lambda expression can be passed in as the filter logic. The following example uses lambda expressions to filter Java collections.

// Create a string list with each string length greater than 2
List <String> filtered = strList. stream (). filter (x-> x. length ()> 2). collect (Collectors. toList ());
System. out. printf ("Original List: % s, filtered list: % s % n", strList, filtered );

Output:

Original List: [abc, bcd, defg, jk], filtered list: [abc, bcd, defg]

In addition, there is a common misunderstanding about the filter () method. In real life, the part is usually discarded when filtering, but the filter () method is used to obtain a new list, and each element of the List conforms to the filtering principle.

Example 8: Apply a function to each element in the list

We usually need to use a function for each element of the list. For example, multiply by a number, divide by a number, or perform other operations. These operations are suitable for the map () method. You can place the conversion logic in the form of lambda expressions in the map () method to convert each element of the set, as shown below.

// Replace the string with uppercase letters and link it with commas
List <String> G7 = Arrays. asList ("USA", "Japan", "France", "Germany", "Italy", "U. k. "," Canada ");
String G7Countries = G7.stream (). map (x-> x. toUpperCase (). collect (Collectors. joining (","));
System. out. println (G7Countries );

Output:

USA, JAPAN, FRANCE, GERMANY, ITALY, U. K., CANADA

Example 9. Copy different values and create a sublist

This example shows how to deduplicate a set using the distinct () method of the stream.

// Create a square list with all different numbers
List <Integer> numbers = Arrays. asList (9, 10, 3, 4, 7, 3, 4 );
List <Integer> distinct = numbers. stream (). map (I-> I * I). distinct (). collect (Collectors. toList ());
System. out. printf ("Original List: % s, Square Without duplicates: % s % n", numbers, distinct );

Output:

Original List: [9, 10, 3, 4, 7, 3, 4], Square Without duplicates: [81,100, 9, 16, 49]

Example 10: calculate the maximum, minimum, sum, and average values of the Set elements.

A useful method for stream classes such as IntStream, LongStream, and DoubleStream is summaryStatistics (). You can return IntSummaryStatistics, LongSummaryStatistics, or DoubleSummaryStatistic s to describe various summary data of elements in the stream. In this example, we use this method to calculate the maximum and minimum values of the list. It also has the getSum () and getAverage () methods to obtain the sum and average of all elements in the list.

// Obtain the number, minimum value, maximum value, sum, and average value of the number.
List <Integer> primes = Arrays. asList (2, 3, 5, 7, 11, 13, 17, 19, 23, 29 );
IntSummaryStatistics stats = primes. stream (). mapToInt (x)-> x). summaryStatistics ();
System. out. println ("Highest prime number in List:" + stats. getMax ());
System. out. println ("Lowest prime number in List:" + stats. getMin ());
System. out. println ("Sum of all prime numbers:" + stats. getSum ());
System. out. println ("Average of all prime numbers:" + stats. getAverage ());

Output:

Highest prime number in List: 29
Lowest prime number in List: 2
Total of all prime numbers: 129
Average of all prime numbers: 12.9

Lambda expressions vs anonymous classes

Since lambda expressions will officially replace anonymous internal classes in Java code, it is necessary to make a comparative analysis of the two. A key difference is the keyword "this. The this keyword of the anonymous class points to the anonymous class, while the this keyword of the lambda expression points to the class that surrounds the lambda expression. Another difference is the compilation method. The Java compiler compiles lambda expressions into private methods of classes. The invokedynamic bytecode command of Java 7 is used to dynamically bind this method.

Java 8 Lambda expressions

10 Java lambda expressions and stream API examples

So far, we have seen 10 lambda expressions in Java 8, which is a suitable task volume for beginners. You may need to run the sample program in person for your understanding. Try to modify the example that requires you to create your own to achieve quick learning. I also recommend that you use Netbeans IDE To practice lambda expressions. It supports Java 8 well. When you convert the code into a function, Netbeans will prompt you in time. With the prompt of Netbeans, you can easily convert an anonymous class into a lambda table. In addition, if you like to read, remember to take a look at lambdas in Java 8 and the book Java 8 Lambdas, pragmatic functional programming in functional programming. The author is Richard Warburton, or you can also look at Manning's Java 8 practice Java 8 in Action). Although this book has not yet been published, I guess there is a free pdf of Chapter 1 online. However, before you start to do other things, let's review the key knowledge of Java 8 lambda expressions, default methods, and functional interfaces.

1) lambda expressions can only be put into the following code: predefined Functional interfaces that use @ Functional annotation, with an Abstract function Method or SAMSingle Abstract Method) type. These are called lambda expressions and can be used as return types or lambda target code parameters. For example, if a method receives Runnable, Comparable, or Callable interfaces, there is a single abstract method, a lambda expression can be passed in. Similarly, if a method accepts interfaces declared in the java. util. function package, such as Predicate, Function, Consumer, or Supplier, it can pass a lambda expression to it.

2) A method can be referenced in a lambda expression. This method is used only when the parameters provided by the lambda expression are not modified. In this example, the lambda expression can be used as a method reference because it is only a simple method call with the same parameters.

List. forEach (n-> System. out. println (n ));
List. forEach (System. out: println); // reference using a method

However, if you have any modification to the parameter, you cannot use method reference. Instead, you need to enter a complete lambda expression, as shown below:

List. forEach (String s)-> System. out. println ("*" + s + "*"));

In fact, the lambda parameter type declaration can be omitted here, And the compiler can infer from the class attribute of the list.

3) static, non-static, and local variables can be used inside lambda, which is called variable capture in lambda.

4) Lambda expressions are also called closures or anonymous functions in Java, so don't be surprised if a colleague calls them closures.

5) Lambda methods are translated into private methods within the compiler, and invokedynamic bytecode commands are distributed for calling. You can use the javap tool in JDK to decompile class files. Use the javap-p or javap-c-v command to view the bytecode generated by the lambda expression. The length should be roughly as follows:

Private static java. lang. Object lambda $0 (java. lang. String );

6) lambda expressions have a limit that only final or final local variables can be referenced. That is to say, variables defined outside the domain cannot be modified within lambda.

List <Integer> primes = Arrays. asList (new Integer [] {2, 3, 5, 7 });
Int factor = 2;
Primes. forEach (element-> {factor ++ ;});

Compile time error: "local variables referenced from a lambda expression must be final or partition tively final"

In addition, you can access it without modifying it, as shown below:

List <Integer> primes = Arrays. asList (new Integer [] {2, 3, 5, 7 });
Int factor = 2;
Primes. forEach (element-> {System. out. println (factor * element );});

Output:

4
6
10
14

Therefore, it looks more like an immutable closure, similar to Python.

The above are all 10 examples of lambda expressions in Java 8. This change will become the largest in Java history and will have a profound impact on the way Java developers use the collection framework in the future. I think the most similar change is the release of Java 5, which brings many advantages and improves the code quality, such as generics, enumeration, and Autoboxing), static import, concurrent API, and variable parameters. The above features make Java code clearer. I think lambda expressions will further improve it. I am looking forward to developing parallel third-party libraries, which can make high-performance applications easier to write.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.