The release date of Java 8 was March 18, 2014, and this groundbreaking release generated a lot of discussion and excitement in the Java community. One feature is the accompanying lambda expression, which will allow us to pass behavior into functions. Prior to Java 8, if you wanted to pass behavior into a function, the only option was an anonymous class, which required six lines of code. The line of code that defines the most important behavior doesn’t stand out in the middle. Lambda expressions replace anonymous classes, eliminating templates and allowing code to be written in a functional style. This is sometimes more readable and clearer. Functional representation and full support for object orientation is an exciting step forward in the Java ecosystem. It will further promote the development of parallel third-party libraries and make full use of multi-core cpus. While it will take Time for the industry to digest Java 8, I don’t think any serious Java developer should lose sight of the core features of the Java release, namely lambda expressions, functional interfaces, streaming apis, default methods, and the new Date and Time apis. As a developer, I’ve found that the best way to learn and master lambda expressions is to experiment and practice with lambda examples as often as possible. Since the biggest impact of the Java 8 release was on the Java Collections Framework, it’s a good idea to practice streaming apis and lambda expressions for extracting, filtering, and sorting Lists and Collections data. I’ve been writing about Java 8 and have shared resources in the past to help you master it. This article shares 10 of the most useful examples of using lambda expressions in code. These are short and concise examples that will help you quickly learn how to use lambda expressions.

Example Java 8 lambda expression

I am personally very excited about the Java 8 release, especially the lambda expressions and streaming apis. The more I know about them, the cleaner CODE I can write. Although it didn’t start out that way. When I first saw Java code written in lambda expressions, I was disappointed by the arcane syntax and thought it made Java unreadable, but I was wrong. After a day of practicing with some examples of lambda expressions and stream apis, I was happy to see clearer Java code. It’s a bit like learning generics, which I hated the first time I saw it. I even continued to use the old Version of Java 1.4 for collections until a friend introduced me to the benefits of using generics. So the basic position is, don’t be afraid of the arcane syntax of lambda expressions and method references, do a few exercises, extract and filter data from collection classes, and you’ll love it. Let’s begin the journey of learning about Java 8 lambda expressions, starting with a simple example.

Example 1: Implement Runnable with lambda expressions

When I started using Java 8, one of the first things I did was replace anonymous classes with lambda expressions, and implementing the Runnable interface is the best example of anonymous classes. Looking at the pre-Java 8 implementation of Runnable, it took four lines of code, compared to one line using lambda expressions. What did we do here? That’s replacing the entire anonymous class with a block of () -> {} code.

1 // Before Java 8:  2 new Thread(new Runnable() { 3 @Override 4 public void run() { 5 System.out.println("Before Java8, too much code for too little to do"); 6 } 7 }).start();Copy the code
New Thread(() -> system.out.println ("In Java8, Lambda expression rocks!!") ) ).start();Copy the code

Output:

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

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 }
Copy the code

For example, if your method does not modify or overwrite arguments, but simply prints something on the console, you could write:

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

If your method takes two arguments, it can be written like this:

(int even, int odd) -> even + odd
Copy the code

By the way, it is common to abbreviate the names of variables inside lambda expressions. This keeps the code shorter and on the same line. So, in the above code, the variable names a, B, or x, y are better than even, odd.

Example 2. Use Java 8 lambda expressions for event handling

If you’ve ever programmed with the Swing API, you’ll remember how to write event listener code. This is another classic use case for an older version of a simple anonymous class, but it can be done now. You can write better event listening code with lambda expressions like this:

JButton show = new JButton(" show "); 3 show.addActionListener(new ActionListener() { 4 @Override 5 public void actionPerformed(ActionEvent e) { 6 System.out.println("Event handling without lambda expression is boring"); 7}});Copy the code
AddActionListener ((e) -> {3 system.out.println ("Light, Camera, Action!! Lambda expressions Rocks"); 4});Copy the code

Another area where Java developers often use anonymous classes is by customizing the Comparator for collections.sort (). In Java 8, you can replace ugly anonymous classes with more readable lambda expressions. I’ll leave this as an exercise. It shouldn’t be too difficult to follow the same steps I used to implement Runnable and ActionListener using lambda expressions.

Example 3. Iterate over the list using lambda expressions

If you’ve worked in Java for a few years, you know that the most common operation for collection classes is to iterate and apply business logic to individual elements, such as processing lists of orders, transactions, and events. Because Java is an imperative language, all looping code prior to Java 8 was sequential, meaning its elements could be parallelized. If you want to do parallel filtering, you have to write your own code, which is not that easy. By introducing lambda expressions and default methods, the question of what to do and how to do it is separated, meaning that Java collections now know how to iterate and can parallelize collection elements at the API level. In the following examples, I’ll show you how to iterate over a list with or without lambda expressions. You can see that the list now has a forEach() method that iterates over all objects and applies your lambda code to them.

AsList ("Lambdas", "Default Method", "Stream API", "Date and Time API"); 3 for (String feature : features) { 4 System.out.println(feature); 5}Copy the code
AsList ("Lambdas", "Default Method", "Stream API", "Date and Time API"); 3 features.forEach(n -> System.out.println(n)); 4 5 // it is more convenient to use Java 8 method references, which are indicated by the :: double colon operator, 6 // looks like C++ scoped parsing operator 7 feature.foreach (system.out ::println);Copy the code

Output:

Lambdas
Default Method
Stream API
Date and Time API
Copy the code

The final example of a list loop shows how to use method references in Java 8. You can see that the double colon, range resolution operator in C++ is now used to indicate method references in Java 8.

Example 4. Use lambda expressions and the functional interface for the Predicate

In addition to supporting the functional programming style at the language level, Java 8 also adds a package called java.util.function. It contains a number of classes to support functional programming in Java. One of them is Predicate, using Java. Util. The function. The Predicate functional interface and lambda expressions, can add logic to the API method, with less code to support more dynamic behavior. The following is an example of Java 8 Predicate, which shows a variety of common ways to filter set data. The Predicate interface is great for filtering.

1 public static void main(args[]){ 2 List languages = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp"); 3 4 System.out.println("Languages which starts with J :"); 5 filter(languages, (str)->str.startsWith("J")); 6 7 System.out.println("Languages which ends with a "); 8 filter(languages, (str)->str.endsWith("a")); 9 10 System.out.println("Print all languages :"); 11 filter(languages, (str)->true); 12 13 System.out.println("Print no language : "); 14 filter(languages, (str)->false); 15 16 System.out.println("Print language whose length greater than 4:"); 17 filter(languages, (str)->str.length() > 4); 18 } 19 20 public static void filter(List names, Predicate condition) { 21 for(String name: names) { 22 if(condition.test(name)) { 23 System.out.println(name + " "); 24} 25} 26}Copy the code

Output:

 1 Languages which starts with J :
 2 Java
 3 Languages which ends with a
 4 Java
 5 Scala
 6 Print all languages :
 7 Java
 8 Scala
 9 C++
10 Haskell
11 Lisp
12 Print no language :
13 Print language whose length greater than 4:
14 Scala
15 Haskell
Copy the code
Public static void filter(List names, Predicate condition) { 3 names.stream().filter((name) -> (condition.test(name))).forEach((name) -> { 4 System.out.println(name + " "); 5}); 6}Copy the code

As you can see, the Stream API’s filter method also accepts a Predicate, which means we can replace our custom filter() method with inline code written inside it, which is the magic of lambda expressions. In addition, the Predicate interface allows you to test multiple conditions, as we’ll see in the next example.

Example 5. How do I add Predicate to a lambda expression

Example, in Java. Util. Function, Predicate allows two or more of a Predicate synthesis. It provides methods similar to the logical operators AND AND OR, named AND (), OR (), AND xor(), to combine conditions passed into the filter() method. For example, to get all four-letter languages that start with J, you can define two separate examples of Predicate representing each condition, and then combine them using the predicate.and () method, as shown below:

1 // You can even combine Predicate with logical functions and(), or(), and xor(), 2 // For example, to find all the names that start with J and are four letters long, You can merge two types of Predicate and pass in 3 types of Predicate<String> startsWithJ = (n) -> n.startswith ("J"); 4 Predicate<String> fourLetterLong = (n) -> n.length() == 4; 5 names.stream() 6 .filter(startsWithJ.and(fourLetterLong)) 7 .forEach((n) -> System.out.print("nName, which starts with 'J' and four letter long is : " + n));Copy the code

Similarly, the OR () and xOR () methods can be used. This example highlights the following points: You can use Predicate as a separate condition and then use them together as needed. In short, you can use the Predicate interface as a traditional Java command, or you can take advantage of lambda expressions to make the difference.

Example 6, Map and Reduce examples using lambda expressions in Java 8

This example introduces the most well-known functional programming concept, Map. It allows you to convert objects. For example, in this case, we convert each element of the costBeforeTax list to an after-tax value. We pass the x -> x*x lambda expression to the map() method, which applies it to every element in the stream. Then print out the list elements with forEach(). Using the collector class of the stream API, you can get all the tax-inclusive overhead. There are methods like toList() that combine the results of a map or any other operation. Because the collector does terminal operations on the stream, the stream cannot be reused afterwards. You can even combine all the numbers into one using the stream API’s Reduce () method, which will be covered in the next example.

1 // Don't use lambda expressions to add 12% tax for each order 2 List costBeforeTax = array.asList (100, 200, 300, 400, 500); 3 for (Integer cost : costBeforeTax) { 4 double price = cost + .12*cost; 5 System.out.println(price); List costBeforeTax = array. asList(100, 200, 300, 400, 500); 10 costBeforeTax.stream().map((cost) -> cost + .12*cost).forEach(System.out::println);Copy the code

Output:

 1 112.0
 2 224.0
 3 336.0
 4 448.0
 5 560.0
 6 112.0
 7 224.0
 8 336.0
 9 448.0
10 560.0
Copy the code

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

In the previous example, you can see that map transforms elements of a collection class, such as a list. There is also a reduce() function that combines all the values into one. Map and Reduce operations are the core operations of functional programming, and Reduce is also called a fold operation because of its functionality. Also, reduce is not a new operation, and chances are you already use it. SQL aggregate functions such as sum(), AVg (), or count() are actually reduce operations because they accept multiple values and return a single value. The reduceh() function defined by the flow API accepts lambda expressions and merges all the values. Classes like IntStream have built-in methods like Average (), count(), and sum() to do reduce operations, as well as mapToLong() and mapToDouble() to do conversions. This doesn’t limit you, you can use built-in methods or you can define your own. In this Java 8 Map Reduce example, we first apply 12% VAT to all prices and then calculate the sum using Reduce ().

1 // Add 12% tax for each order 2 // old method: 3 List costBeforeTax = Arrays. AsList (100, 200, 300, 400, 500); 4 double total = 0; 5 for (Integer cost : costBeforeTax) { 6 double price = cost + .12*cost; 7 total = total + price; 8 } 9 System.out.println("Total : " + total); 10 11 // New method: 12 List costBeforeTax = array. asList(100, 200, 300, 400, 500); 13 double bill = costBeforeTax.stream().map((cost) -> cost + .12*cost).reduce((sum, cost) -> sum + cost).get(); 14 System.out.println("Total : " + bill);Copy the code

Output:

Total: 1680.0 Total: 1680.0Copy the code

Example 7. Create a list of strings by filtering

Filtering is a common practice of Java developers on large collections, and it is now surprisingly simple to filter large collections of data using lambda expressions and streaming apis. Streams provide a filter() method that takes a Predicate object, which can be passed a lambda expression as filtering logic. The following example of filtering a Java collection with lambda expressions will help you understand.

// Create a list of strings Each String contains more than 2 characters. 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);Copy the code

Output:

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

Also, there is a common misconception about the filter() method. In real life, when you do filtering, you normally discard parts, but using filter() gets a new list with each element matching the filter principle.

Example 8. Apply the function to each element of the list

We usually need to use some function for each element of a list, such as multiplying by a number, dividing by a number, or doing something else. All of these operations are well suited to the map() method, which transforms each element of the collection by putting the transformation logic in the form of a lambda expression in the map() method, as shown below.

List<String> G7 = array. asList("USA", "Japan", "France", "Germany", "Italy", "U.K.","Canada"); String G7Countries = G7.stream().map(x -> x.toUpperCase()).collect(Collectors.joining(", ")); System.out.println(G7Countries);Copy the code

Output:

USA, JAPAN, FRANCE, GERMANY, ITALY, U.K., CANADA
Copy the code

Example 9. Create a sublist by copying different values

This example shows how to use the distinct() method of a stream to de-duplicate a collection.

List<Integer> numbers = array.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);Copy the code

Output:

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

Example 10. Calculate the maximum, minimum, sum, and average values of set elements

One of the most useful classes for streams such as IntStream, LongStream, and DoubleStream is a method called summaryStatistics(). You can return IntSummaryStatistics, LongSummaryStatistics, or DoubleSummaryStatistic s that describe various summary data for elements in the flow. In this case, we use this method to calculate the maximum and minimum values of the list. It also has getSum() and getAverage() methods to get the sum and average of all the elements of the list.

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());Copy the code

Output:

Highest prime number in List : 29 Lowest prime number in List : 2 Sum of all prime numbers : 129 Average of All Prime Numbers: 12.9Copy the code

Lambda expressions vs anonymous classes

Now that lambda expressions are about to formally replace anonymous inner classes in Java code, it’s worth doing a comparative analysis. One key difference is the this keyword. The this keyword for anonymous classes points to anonymous classes, while the this keyword for lambda expressions points to classes enclosing lambda expressions. Another difference is how they compile. The Java compiler compiles lambda expressions into private methods of the class. This method is dynamically bound using Java 7’s Invokedynamic bytecode directive.

Java 8 Lambda expression essentials

10 Examples of Java lambda expressions and stream apis

So far we’ve seen 10 lambda expressions for Java 8, which is a reasonable amount of work for a novice, and you may need to run the sample program yourself to get the hang of it. Try modifying the requirements to create your own examples for quick learning purposes. I would also like to recommend using Netbeans IDE to practice lambda expressions, which supports Java 8 well. Netbeans will give you a prompt when converting your code to functional form. It’s easy to convert anonymous classes into lambda expressions just by following Netbeans’ tips. Also, if you like reading, remember to take a look at the Java 8 Lambdas, pragmatic Functional Programming, written by Richard Warburton, Or check out Manning’s Java 8 in Action, which isn’t out yet, but I guess the first chapter is available online as a free PDF. Before you get busy with anything else, though, let’s review the highlights of Java 8’s lambda expressions, default methods, and functional interfaces.

Lambda expressions can only be put into code that pre-defines a Functional interface using the @functional annotation, has a Method with an Abstract function, or has a SAM (Single Abstract Method) type. These target types, called lambda expressions, can be used as return types, or as arguments to the lambda object code. For example, if a method receives a Runnable, Comparable, or Callable interface, there is a single abstract method that can be passed in as a lambda expression. Similarly, a method can be passed a lambda expression if it accepts an interface declared in the java.util.function package, such as Predicate, function, Consumer, or Supplier.

2) Method references can be used within a lambda expression only if the method does not modify the arguments provided by the lambda expression. The lambda expression in this case can be replaced with a method reference, because this is just a simple method call with the same parameters.

list.forEach(n -> System.out.println(n)); list.forEach(System.out::println); // Use method referencesCopy the code

However, if you make any changes to the parameters, you cannot use a method reference and instead type the full lambda expression, as shown below:

list.forEach((String s) -> System.out.println("*" + s + "*"));
Copy the code

In fact, you can omit the type declaration of the lambda argument here, which the compiler can infer from the class attributes of the list.

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

4) Lambda expressions are also known as closures or anonymous functions in Java, so don’t be surprised if some colleagues call them closures.

5) Lambda methods are translated into private methods inside the compiler and dispatched with invokedynamic bytecode instructions to invoke. You can decompile class files using the Javap tools in the JDK. Use the javap -p or javap -c -v command to take a look at the bytecode generated by a lambda expression. It should look something like this:

private static java.lang.Object lambda$0(java.lang.String);
Copy the code

6) Lambda expressions have the limitation that they can only reference final or final local variables, which means that variables defined outside the domain cannot be modified inside the lambda.

List<Integer> primes = Arrays. AsList (new Integer[]{2, 3,5,7}); int factor = 2; primes.forEach(element -> { factor++; });Copy the code
Compile time error : "local variables referenced from a lambda expression must be final or effectively final"
Copy the code

In addition, it is possible to simply 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); });Copy the code

Output:

4 June 10 of 14Copy the code

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

Those are all 10 examples of Java 8 lambda expressions. This change will be the largest in Java history and will have a profound impact on the way Java developers will use the collections framework in the future. I think the most similar change was the release of Java 5, which brought a number of benefits and improved code quality, such as generics, enumerations, Autoboxing, static imports, concurrent apis, and variable arguments. The above features make Java code much cleaner, and I think lambda expressions will improve it further. I’m looking forward to developing parallel third-party libraries that will make high-performance applications easier to write.

References:Javarevisited.blogspot.com/2014/02/10-…