摘要:原文
Introduction (Business Case)
Lambda expressions are a new and important feature included in Java SE 8. A lambda expression provides a way to represent one method interface using an expression. A lambda expression is like a method, it provides a list of formal parameters and a body (which can be an expression or a block of code) expressed in terms of those parameters.
Lambda expressions also improve the Collection libraries. Java SE 8 added two packages related to bulk data operations for Collections, the java.util.function package, and the java.util.stream. A stream is like an iterator, but with a lot of extra functionality. Taken together, lambda expressions and streams are the biggest change to Java programming since the generics and annotations were added to the language. In this article, we will explore the power of lambda expressions and streams, from simple to complex examples.
If you haven’t installed Java 8, then this is the first thing you should do to be able to work with lambdas and streams. Tools and IDE’s like NetBeans and IntelliJ IDEA support Java 8 features, such as lambda expressions, repeatable annotations, compact profiles and others.
Below are the download links for Java SE 8 and NetBeans IDE 8:
Java Platform (JDK 8): Download Java 8 from Oracle, it can also be bundled with NetBeans IDE
NetBeans IDE 8: Download NetBeans IDE from the NetBeans official site
Lambda Expressions SyntaxThe basic syntax of a lambda is either:
(parameters) ->expression or (parameters) ->{ statements; }
The following are examples of Java lambda expressions:
1. () -> 5 // takes no value and returns 5 2. x -> 2 * x // takes a number and returns the result of doubling it 3. (x, y) -> x – y // takes two numbers and returns their difference 4. (int x, int y) -> x + y // takes two integers and returns their sum 5. (String s) -> System.out.print(s) // takes a string and prints it to console without returning anythingBasic Lambdas Examples
Now that we have an idea of what lambdas are, let us start with some basic examples. In this section, we will see how lambda expressions affect the way we code. Having a list of players, the “for loop”, as programmers often refers to the for statement, can be translated in Java SE 8 as below:
String[] atp = {"Rafael Nadal", "Novak Djokovic", "Stanislas Wawrinka", "David Ferrer", "Roger Federer", "Andy Murray", "Tomas Berdych", "Juan Martin Del Potro"}; Listplayers = Arrays.asList(atp); // Old looping for (String player : players) { System.out.print(player + "; "); } // Using lambda expression and functional operations players.forEach((player) -> System.out.print(player + "; ")); // Using double colon operator in Java 8 players.forEach(System.out::println); As you can see, lambda expressions can reduced our code to one single line. Another example is in a graphical user interface application, when anonymous classes can be replaced with lambda expressions. The same thing happens when implementing the Runnable interface: // Using anonymous innerclass btn.setOnAction(new EventHandler () { @Override public void handle(ActionEvent event) { System.out.println("Hello World!"); } }); // Using lambda expression btn.setOnAction(event -> System.out.println("Hello World!"));
Here is how we can write a Runnable using lambdas:
// Using anonymous innerclass new Thread(new Runnable() { @Override public void run() { System.out.println("Hello world !"); } }).start(); // Using lambda expression new Thread(() -> System.out.println("Hello world !")).start(); // Using anonymous innerclass Runnable race1 = new Runnable() { @Override public void run() { System.out.println("Hello world !"); } }; // Using lambda expression Runnable race2 = () -> System.out.println("Hello world !"); // Run em! race1.run(); race2.run();
The Runnable lambda expression, which uses the block format, converts five lines of code into one statement. Going further, in the next section we will use lambdas for sorting collections.
Sorting Collections with LambdasIn Java, the Comparator class is used for sorting collections. In the following examples, we will sort a list of players based on name, surname, name length and last name letter. We will first sort them as we did before, using anonymous inner classes, and then reduce our code using lambda expressions.
In the first example, we will sort our list by name. Using the old way, this looks like this:
String[] players = {"Rafael Nadal", "Novak Djokovic", "Stanislas Wawrinka", "David Ferrer", "Roger Federer", "Andy Murray", "Tomas Berdych", "Juan Martin Del Potro", "Richard Gasquet", "John Isner"}; // Sort players by name using anonymous innerclass Arrays.sort(players, new Comparator() { @Override public int compare(String s1, String s2) { return (s1.compareTo(s2)); } });
With lambdas, the same thing can be achieved like this:
// Sort players by name using lambda expression ComparatorsortByName = (String s1, String s2) -> (s1.compareTo(s2)); Arrays.sort(players, sortByName); // or this Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2)));
The remaining sorts are listed below. The same as the above example, the code applies a Comparator by using an anonymous inner class and a couple of lambda expressions:
// Sort players by surname using anonymous innerclass Arrays.sort(players, new Comparator() { @Override public int compare(String s1, String s2) { return (s1.substring(s1.indexOf(" ")).compareTo(s2.substring(s2.indexOf(" ")))); } }); // Sort players by surname using lambda expression Comparator sortBySurname = (String s1, String s2) -> (s1.substring(s1.indexOf(" ")).compareTo(s2.substring(s2.indexOf(" ")))); Arrays.sort(players, sortBySurname); // or this Arrays.sort(players, (String s1, String s2) -> (s1.substring(s1.indexOf(" ")).compareTo(s2.substring(s2.indexOf(" "))))); // Sort players by name lenght using anonymous innerclass Arrays.sort(players, new Comparator () { @Override public int compare(String s1, String s2) { return (s1.length() - s2.length()); } }); // Sort players by name lenght using lambda expression Comparator sortByNameLenght = (String s1, String s2) -> (s1.length() - s2.length()); Arrays.sort(players, sortByNameLenght); // or this Arrays.sort(players, (String s1, String s2) -> (s1.length() - s2.length())); // Sort players by last letter using anonymous innerclass Arrays.sort(players, new Comparator () { @Override public int compare(String s1, String s2) { return (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1)); } }); // Sort players by last letter using lambda expression Comparator sortByLastLetter = (String s1, String s2) -> (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1)); Arrays.sort(players, sortByLastLetter); // or this Arrays.sort(players, (String s1, String s2) -> (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1)));
That’s all, pretty straightforward. We will explore more lambdas capabilities in the next section, where we will combine them with streams.
Working with Lambdas and StreamsStreams are wrappers around collections that use lambdas pervasively. They support many operations that use lambdas, like map, filter, limit, sorted, count, min, max, sum, collect and others. Also, streams use lazy evaluation and they are not actually reading all the data and methods like getFirst() can end the stream. In the next examples, we will explore what lambdas and streams can do. We created a Person class and use this class to add some data to a list that will be used in further streams operations. The Person class is just a simple POJO:
public class Person { private String firstName, lastName, job, gender; private int salary, age; public Person(String firstName, String lastName, String job, String gender, int age, int salary) { this.firstName = firstName; this.lastName = lastName; this.gender = gender; this.age = age; this.job = job; this.salary = salary; } // Getter and Setter . . . . . }
Going further, we will create two lists, both containing Person objects:
ListjavaProgrammers = new ArrayList () { { add(new Person("Elsdon", "Jaycob", "Java programmer", "male", 43, 2000)); add(new Person("Tamsen", "Brittany", "Java programmer", "female", 23, 1500)); add(new Person("Floyd", "Donny", "Java programmer", "male", 33, 1800)); add(new Person("Sindy", "Jonie", "Java programmer", "female", 32, 1600)); add(new Person("Vere", "Hervey", "Java programmer", "male", 22, 1200)); add(new Person("Maude", "Jaimie", "Java programmer", "female", 27, 1900)); add(new Person("Shawn", "Randall", "Java programmer", "male", 30, 2300)); add(new Person("Jayden", "Corrina", "Java programmer", "female", 35, 1700)); add(new Person("Palmer", "Dene", "Java programmer", "male", 33, 2000)); add(new Person("Addison", "Pam", "Java programmer", "female", 34, 1300)); } }; List phpProgrammers = new ArrayList () { { add(new Person("Jarrod", "Pace", "PHP programmer", "male", 34, 1550)); add(new Person("Clarette", "Cicely", "PHP programmer", "female", 23, 1200)); add(new Person("Victor", "Channing", "PHP programmer", "male", 32, 1600)); add(new Person("Tori", "Sheryl", "PHP programmer", "female", 21, 1000)); add(new Person("Osborne", "Shad", "PHP programmer", "male", 32, 1100)); add(new Person("Rosalind", "Layla", "PHP programmer", "female", 25, 1300)); add(new Person("Fraser", "Hewie", "PHP programmer", "male", 36, 1100)); add(new Person("Quinn", "Tamara", "PHP programmer", "female", 21, 1000)); add(new Person("Alvin", "Lance", "PHP programmer", "male", 38, 1600)); add(new Person("Evonne", "Shari", "PHP programmer", "female", 40, 1800)); } };
Let’s now use the forEach method to iterate the above lists:
System.out.println("Show programmers names:"); javaProgrammers.forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName())); phpProgrammers.forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName())); We will now use the same forEach method and try to increase programmer’s salary by 5%: System.out.println("Increase salary by 5% to programmers:"); ConsumergiveRaise = e -> e.setSalary(e.getSalary() / 100 * 5 + e.getSalary()); javaProgrammers.forEach(giveRaise); phpProgrammers.forEach(giveRaise); Another useful method is the filter method. To make use of that, let’s show PHP programmers that earn more than $1,400: System.out.println("Show PHP programmers that earn more than $1,400:") phpProgrammers.stream() .filter((p) -> (p.getSalary() > 1400)) .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName())); We can also define filters and then reuse them in further operations: // Define some filters Predicate ageFilter = (p) -> (p.getAge() > 25); Predicate salaryFilter = (p) -> (p.getSalary() > 1400); Predicate genderFilter = (p) -> ("female".equals(p.getGender())); System.out.println("Show female PHP programmers that earn more than $1,400 and are older than 24 years:"); phpProgrammers.stream() .filter(ageFilter) .filter(salaryFilter) .filter(genderFilter) .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName())); // Reuse filters System.out.println("Show female Java programmers older than 24 years:"); javaProgrammers.stream() .filter(ageFilter) .filter(genderFilter) .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName())); Results can also be limited, if we use the limit method: System.out.println("Show first 3 Java programmers:"); javaProgrammers.stream() .limit(3) .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName())); System.out.println("Show first 3 female Java programmers:"); javaProgrammers.stream() .filter(genderFilter) .limit(3) .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));
What about sorting? Can we do that with streams? The answer is yes, we can. In the examples below, we will sort Java programmers by name and salary, collect them into a list and then show the list:
System.out.println("Sort and show the first 5 Java programmers by name:"); ListsortedJavaProgrammers = javaProgrammers .stream() .sorted((p, p2) -> (p.getFirstName().compareTo(p2.getFirstName()))) .limit(5) .collect(toList()); sortedJavaProgrammers.forEach((p) -> System.out.printf("%s %s; %n", p.getFirstName(), p.getLastName())); System.out.println("Sort and show Java programmers by salary:"); sortedJavaProgrammers = javaProgrammers .stream() .sorted((p, p2) -> (p.getSalary() - p2.getSalary())) .collect(toList()); sortedJavaProgrammers.forEach((p) -> System.out.printf("%s %s; %n", p.getFirstName(), p.getLastName()));
If we are interested only in the lowest and the highest salary, faster than sorting and choosing the first (or the last) are the min and max methods:
System.out.println("Get the lowest Java programmer salary:"); Person pers = javaProgrammers .stream() .min((p1, p2) -> (p1.getSalary() - p2.getSalary())) .get() System.out.printf("Name: %s %s; Salary: $%,d.", pers.getFirstName(), pers.getLastName(), pers.getSalary()) System.out.println("Get the highest Java programmer salary:"); Person person = javaProgrammers .stream() .max((p, p2) -> (p.getSalary() - p2.getSalary())) .get() System.out.printf("Name: %s %s; Salary: $%,d.", person.getFirstName(), person.getLastName(), person.getSalary())
We have already seen above an example on how the collect method works. Combined with the map method, we can use collect method to gather our results in a String, in a Set or in a TreeSet:
System.out.println("Get PHP programmers first name to String:"); String phpDevelopers = phpProgrammers .stream() .map(Person::getFirstName) .collect(joining(" ; ")); // this can be used as a token in further operations System.out.println("Get Java programmers first name to Set:"); SetjavaDevFirstName = javaProgrammers .stream() .map(Person::getFirstName) .collect(toSet()); System.out.println("Get Java programmers last name to TreeSet:"); TreeSet javaDevLastName = javaProgrammers .stream() .map(Person::getLastName) .collect(toCollection(TreeSet::new)); Streams can also be parallel. An example is below: System.out.println("Calculate total money spent for paying Java programmers:"); int totalSalary = javaProgrammers .parallelStream() .mapToInt(p -> p.getSalary()) .sum(); To obtain various summary data about the elements of a stream we can use the summaryStatistics method. Going further, we then have access to methods like getMax, getMin, getSum or getAverage: //Get count, min, max, sum, and average for numbers List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); IntSummaryStatistics stats = numbers .stream() .mapToInt((x) -> x) .summaryStatistics(); System.out.println("Highest number in List : " + stats.getMax()); System.out.println("Lowest number in List : " + stats.getMin()); System.out.println("Sum of all numbers : " + stats.getSum()); System.out.println("Average of all numbers : " + stats.getAverage());
That’s all, hope you like it!
ConclusionIn this article, we have discovered different ways of using lambda expressions, starting from basic examples to complex ones, where we used lambdas with streams. Moreover, we have also learned how to use lambda expressions with the Comparator class for sorting Java collections.
原文:Start Using Java Lambda Expressions
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/64791.html
摘要:摘要添加了表達(dá)式閉包和特性支持,包括方法的引用,增強(qiáng)類(lèi)型推斷,和虛擬擴(kuò)展方法。圍繞的語(yǔ)言功能支持包括虛擬擴(kuò)展方法,這將使接口的源代碼和二進(jìn)制兼容的方式演變升級(jí)。 Author:Joseph D. Darcy Organization:Oracle Owner:Brian Goetz Created:2011/11/1 Updated:2013/2/21 Type:Feature Sta...
摘要:在支持一類(lèi)函數(shù)的語(yǔ)言中,表達(dá)式的類(lèi)型將是函數(shù)。匿名函數(shù)的返回類(lèi)型與該主體表達(dá)式一致如果表達(dá)式的主體包含一條以上語(yǔ)句,則表達(dá)式必須包含在花括號(hào)中形成代碼塊。注意,使用表達(dá)式的方法不止一種。 摘要:此篇文章主要介紹 Java8 Lambda 表達(dá)式產(chǎn)生的背景和用法,以及 Lambda 表達(dá)式與匿名類(lèi)的不同等。本文系 OneAPM 工程師編譯整理。 Java 是一流的面向?qū)ο笳Z(yǔ)言,除了部分簡(jiǎn)...
摘要:表達(dá)式還增強(qiáng)了集合庫(kù)。和前面的示例一樣先使用匿名內(nèi)部類(lèi)來(lái)排序然后再使用表達(dá)式精簡(jiǎn)我們的代碼。使用舊的方式代碼如下所示使用匿名內(nèi)部類(lèi)根據(jù)排序使用可以通過(guò)下面的代碼實(shí)現(xiàn)同樣的功能使用排序也可以采用如下形式其他的排序如下所示。 本文轉(zhuǎn)自:http://blog.csdn.net/renfufei...轉(zhuǎn)載請(qǐng)注明出處 原文鏈接: Start Using Java Lambda Expressi...
摘要:表達(dá)式又名閉包匿名函數(shù)筆記根據(jù)終于在中引入了表達(dá)式。函數(shù)式接口要介紹中表達(dá)式的實(shí)現(xiàn),需要知道什么是函數(shù)式接口。但同樣需要保證外部的自由變量不能在表達(dá)式中被改變。 Java Lambda 表達(dá)式(又名閉包 (Closure)/ 匿名函數(shù) ) 筆記 根據(jù) JSR 335, Java 終于在 Java 8 中引入了 Lambda 表達(dá)式。也稱(chēng)之為閉包或者匿名函數(shù)。 showImg(https...
閱讀 1111·2021-09-22 16:04
閱讀 1494·2019-08-30 15:43
閱讀 1097·2019-08-29 14:01
閱讀 3438·2019-08-26 12:19
閱讀 3353·2019-08-26 12:15
閱讀 1444·2019-08-26 12:13
閱讀 3264·2019-08-23 17:00
閱讀 1484·2019-08-23 15:38