Lambda表达式常用代码示例
Lambda表達(dá)式常用代碼示例
2017-10-24
目錄
1 Lambda表達(dá)式是什么
2 Lambda表達(dá)式語(yǔ)法
3 函數(shù)式接口是什么
? 3.1 常用函數(shù)式接口
4 Lambdas和Streams結(jié)合使用
? 4.1 使用forEach方法
? 4.2 使用過(guò)濾器filter方法
? 4.3 使用limit方法
? 4.4 使用sorted方法
? 4.5 使用map方法
? 4.6 使用parallelStream方法
? 4.7 使用summaryStatistics方法
參考?
?
1 Lambda表達(dá)式是什么?
?返回
Lambda 表達(dá)式是一種匿名函數(shù)(對(duì) Java 而言這并不完全正確。在Java中,Lambda 表達(dá)式是對(duì)象,他們必須依附于一類(lèi)特別的對(duì)象類(lèi)型——函數(shù)式接口(functional interface))。Lambda表達(dá)式是Java SE 8中一個(gè)重要的新特性。lambda表達(dá)式就和方法一樣,它提供了一個(gè)正常的參數(shù)列表(argument)和一個(gè)使用這些參數(shù)的主體(body)。
Lambda 表達(dá)式為 Java 添加了缺失的函數(shù)式編程特點(diǎn),使我們能將函數(shù)當(dāng)做一等公民看待。
Lambda表達(dá)式還增強(qiáng)了集合庫(kù)。 Java SE 8添加了2個(gè)對(duì)集合數(shù)據(jù)進(jìn)行批量操作的包: java.util.function 包以及java.util.stream 包。 流(stream)就如同迭代器(iterator),但附加了許多額外的功能。 總的來(lái)說(shuō),lambda表達(dá)式和 stream 是自Java語(yǔ)言添加泛型(Generics)和注解(annotation)以來(lái)最大的變化。
2 Lambda表達(dá)式語(yǔ)法
?返回
Java 中的 Lambda 表達(dá)式通常使用 (argument) -> {body}?語(yǔ)法書(shū)寫(xiě),例如:
(arg1, arg2...) -> { body } (type1 arg1, type2 arg2...) -> { body }以下是一些 Lambda 表達(dá)式的例子:
(int a, int b) -> { return a + b; } () -> System.out.println("Hello World"); (String s) -> { System.out.println(s); } () -> 42 () -> { return 3.1415 };Lambda表達(dá)式結(jié)構(gòu)說(shuō)明:
- 一個(gè) Lambda 表達(dá)式可以有零個(gè)或多個(gè)參數(shù)
- 參數(shù)的類(lèi)型既可以明確聲明,也可以根據(jù)上下文來(lái)推斷。例如:(int a)與(a)效果相同
- 所有參數(shù)需包含在圓括號(hào)內(nèi),參數(shù)之間用逗號(hào)相隔。例如:(a, b) 或 (int a, int b) 或 (String a, int b, float c)
- 空?qǐng)A括號(hào)代表參數(shù)集為空。例如:() -> 42
- 當(dāng)只有一個(gè)參數(shù),且其類(lèi)型可推導(dǎo)時(shí),圓括號(hào)()可省略。例如:a -> return a*a
- Lambda 表達(dá)式的主體可包含零條或多條語(yǔ)句
- 如果 Lambda 表達(dá)式的主體只有一條語(yǔ)句,花括號(hào){}可省略。匿名函數(shù)的返回類(lèi)型與該主體表達(dá)式一致
- 如果 Lambda 表達(dá)式的主體包含一條以上語(yǔ)句,則表達(dá)式必須包含在花括號(hào){}中(形成代碼塊)。匿名函數(shù)的返回類(lèi)型與代碼塊的返回類(lèi)型一致,若沒(méi)有返回則為空
3 函數(shù)式接口是什么
?返回
函數(shù)式接口是只包含一個(gè)抽象方法聲明的接口。
java.lang.Runnable 就是一種函數(shù)式接口,在 Runnable 接口中只聲明了一個(gè)方法 void run(),相似地,ActionListener 接口也是一種函數(shù)式接口,我們使用匿名內(nèi)部類(lèi)來(lái)實(shí)例化函數(shù)式接口的對(duì)象,有了 Lambda 表達(dá)式,這一方式可以得到簡(jiǎn)化。Runnable接口代碼如下:
@FunctionalInterface public interface Runnable {public abstract void run(); }?每個(gè) Lambda 表達(dá)式都能隱式地賦值給函數(shù)式接口。如下代碼:
Runnable r = () -> System.out.println("hello world");Runnable的Lambda表達(dá)式和匿名內(nèi)部類(lèi)的使用示例
public void sample01() {// 1.1使用匿名內(nèi)部類(lèi)new Thread(new Runnable() {@Overridepublic void run() {System.out.println("1.1 Hello world !");}}).start();// 1.2使用 lambda expressionnew Thread(() -> System.out.println("1.2 Hello world !")).start();// 2.1使用匿名內(nèi)部類(lèi)Runnable race1 = new Runnable() {@Overridepublic void run() {System.out.println("1.3 Hello world !");}};// 2.2使用 lambda expressionRunnable race2 = () -> System.out.println("1.4 Hello world !");// 直接調(diào)用 run 方法(沒(méi)開(kāi)新線程哦!) race1.run();race2.run();} View Code自定義函數(shù)式接口及Lambda表達(dá)式和匿名內(nèi)部類(lèi)的使用示例
WorkerInterface.java
//定義一個(gè)函數(shù)式接口 @FunctionalInterface public interface WorkerInterface {public void doSomeWork(); } View CodeWorkerInterfaceTest.java
public class WorkerInterfaceTest {public static void main(String [] args) {//invoke doSomeWork using Annonymous classexecute(new WorkerInterface() {@Overridepublic void doSomeWork() {System.out.println("Worker invoked using Anonymous class");}});//invoke doSomeWork using Lambda expressionexecute( () -> System.out.println("Worker invoked using Lambda expression") );}public static void execute(WorkerInterface worker) {worker.doSomeWork();} } View Code3.1 常用函數(shù)式接口
Predicate、Function、Consumer、Supplier示例代碼:
//Predicate 接口只有一個(gè)參數(shù),返回boolean類(lèi)型。。Predicate<String> predicate = (s) -> s.length() > 3;System.out.println(predicate.test("foo")); // falsePredicate<Boolean> nonNull = Objects::nonNull; System.out.println(nonNull.test(false)); // true //Function 接口接受一個(gè)參數(shù),返回一個(gè)結(jié)果,并附帶了一些可以和其他函數(shù)組合的默認(rèn)方法(compose, andThen) Function<String, Integer> toInteger = Integer::valueOf; System.out.println(toInteger.apply("123").getClass()); //class java.lang.Integer Function<String, String> backToString = toInteger.andThen(String::valueOf); System.out.println(backToString.apply("123").getClass()); //class java.lang.String //Consumer 接口接受一個(gè)參數(shù),沒(méi)有返回結(jié)果。 Consumer<Cat> greeter = (c) -> System.out.println("Hello, " + c.name); Cat cat=new Cat("Tom", 3); greeter.accept(cat); //Hello, Tom //Supplier接口沒(méi)有參數(shù),。 Supplier<Double> number = () -> Math.random(); System.out.println(number.get()); //0.8765252430762529 View Code使用Lambdas排序集合
在Java中,Comparator 類(lèi)被用來(lái)排序集合。
使用匿名內(nèi)部類(lèi)或Lambda表達(dá)式根據(jù) name 排序 players:
String[] players = {"Rafael Nadal", "Novak Djokovic", "Stanislas Wawrinka", "David Ferrer","Roger Federer", "Andy Murray", "Tomas Berdych", "Juan Martin Del Potro","Richard Gasquet", "John Isner"};// 1.1 使用匿名內(nèi)部類(lèi)根據(jù) name 排序 playersArrays.sort(players, new Comparator<String>() {@Overridepublic int compare(String s1, String s2) {return (s1.compareTo(s2));}});// 1.2 使用 lambda expression 排序 playersComparator<String> sortByName = (String s1, String s2) -> (s1.compareTo(s2));Arrays.sort(players, sortByName);// 1.3 也可以采用如下形式:Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2))); View Code?其他排序:
// 2.1 使用匿名內(nèi)部類(lèi)根據(jù) surname 排序 playersArrays.sort(players, new Comparator<String>() {@Overridepublic int compare(String s1, String s2) {return (s1.substring(s1.indexOf(" ")).compareTo(s2.substring(s2.indexOf(" "))));}});// 2.2 使用 lambda expression 排序,根據(jù) surnameComparator<String> sortBySurname = (String s1, String s2) ->( s1.substring(s1.indexOf(" ")).compareTo( s2.substring(s2.indexOf(" ")) ) );Arrays.sort(players, sortBySurname);// 2.3 或者這樣,懷疑原作者是不是想錯(cuò)了,括號(hào)好多...Arrays.sort(players, (String s1, String s2) ->( s1.substring(s1.indexOf(" ")).compareTo( s2.substring(s2.indexOf(" ")) ) ));// 3.1 使用匿名內(nèi)部類(lèi)根據(jù) name lenght 排序 playersArrays.sort(players, new Comparator<String>() {@Overridepublic int compare(String s1, String s2) {return (s1.length() - s2.length());}});// 3.2 使用 lambda expression 排序,根據(jù) name lenghtComparator<String> sortByNameLenght = (String s1, String s2) -> (s1.length() - s2.length());Arrays.sort(players, sortByNameLenght);// 3.3 or thisArrays.sort(players, (String s1, String s2) -> (s1.length() - s2.length()));// 4.1 使用匿名內(nèi)部類(lèi)排序 players, 根據(jù)最后一個(gè)字母Arrays.sort(players, new Comparator<String>() {@Overridepublic int compare(String s1, String s2) {return (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1));}});// 4.2 使用 lambda expression 排序,根據(jù)最后一個(gè)字母Comparator<String> sortByLastLetter =(String s1, String s2) ->(s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1));Arrays.sort(players, sortByLastLetter);// 4.3 or thisArrays.sort(players, (String s1, String s2) -> (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1))); View Code4 Lambdas和Streams結(jié)合使用
?返回
Stream是對(duì)集合的包裝,通常和lambda一起使用。 使用lambdas可以支持許多操作,如 map, filter, limit, sorted, count, min, max, sum, collect 等等。 同樣,Stream使用懶運(yùn)算,他們并不會(huì)真正地讀取所有數(shù)據(jù),遇到像getFirst() 這樣的方法就會(huì)結(jié)束鏈?zhǔn)秸Z(yǔ)法。
Person.java代碼:
public class Person {private String firstName;private String lastName;private String job;private String gender;private int salary;private int age;public Person(String firstName, String lastName, String job,String gender, int age, int salary) {this.setFirstName(firstName);this.setLastName(lastName);this.setGender(gender);this.setAge(age);this.setJob(job);this.setSalary(salary);}public String getFirstName() {return firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}public String getLastName() {return lastName;}public void setLastName(String lastName) {this.lastName = lastName;}public String getJob() {return job;}public void setJob(String job) {this.job = job;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public int getSalary() {return salary;}public void setSalary(int salary) {this.salary = salary;}public int getAge() {return age;}public void setAge(int age) {this.age = age;} } View Code初始化Person代碼:
List<Person> javaProgrammers = new ArrayList<Person>() {{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<Person> phpProgrammers = new ArrayList<Person>() {{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));}}; View Code4.1 使用forEach方法
使用forEach方法顯示所有程序員姓名:
System.out.println("所有程序員的姓名:");javaProgrammers.forEach((p) -> System.out.println(String.format("%s %s; ", p.getFirstName(), p.getLastName())));phpProgrammers.forEach((p) -> System.out.println(String.format("%s %s; ", p.getFirstName(), p.getLastName()))); View CodeForEach代碼:
public interface Iterable<T> {default void forEach(Consumer<? super T> action) {Objects.requireNonNull(action);for (T t : this) {action.accept(t);}}...} View Code使用forEach方法,增加程序員的工資5%:
System.out.println("給程序員加薪 5% :");Consumer<Person> giveRaise = e -> e.setSalary(e.getSalary() / 100 * 5 + e.getSalary());javaProgrammers.forEach(giveRaise);phpProgrammers.forEach(giveRaise); View Code4.2 使用過(guò)濾器filter方法?
System.out.println("下面是月薪超過(guò) $1,400 的PHP程序員:");phpProgrammers.stream().filter((p) -> (p.getSalary() > 1400)).forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));// 定義 filters Predicate<Person> ageFilter = (p) -> (p.getAge() > 25);Predicate<Person> salaryFilter = (p) -> (p.getSalary() > 1400);Predicate<Person> genderFilter = (p) -> ("female".equals(p.getGender()));System.out.println("下面是年齡大于 25歲且月薪在$1,400以上的女PHP程序員:");phpProgrammers.stream().filter(ageFilter).filter(salaryFilter).filter(genderFilter).forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName())); View Code4.3 使用limit方法
?使用limit方法可以限制結(jié)果集的個(gè)數(shù):
System.out.println("最前面的3個(gè) Java programmers:");javaProgrammers.stream().limit(3).forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));System.out.println("最前面的3個(gè)女性 Java programmers:");javaProgrammers.stream().filter(genderFilter).limit(3).forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName())); View Code4.4 使用sorted方法
使用sorted方法進(jìn)行排序:
System.out.println("根據(jù) name 排序,并顯示前5個(gè) Java programmers:");List<Person> sortedJavaProgrammers = 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("根據(jù) salary 排序 Java programmers:");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())); View Code使用min和max方法:
System.out.println("工資最低的 Java programmer:");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("工資最高的 Java programmer:");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()); View Code4.5 使用map方法
結(jié)合 map 方法,我們可以使用 collect 方法來(lái)將我們的結(jié)果集放到一個(gè)字符串,一個(gè) Set 或一個(gè)TreeSet中:
System.out.println("將 PHP programmers 的 first name 拼接成字符串:");String phpDevelopers = phpProgrammers.stream().map(Person::getFirstName).collect(joining(" ; ")); // 在進(jìn)一步的操作中可以作為標(biāo)記(token)System.out.println(phpDevelopers); //Jarrod ; Clarette ; Victor ; Tori ; Osborne ; Rosalind ; Fraser ; Quinn ; Alvin ; Evonne System.out.println("將 Java programmers 的 first name 存放到 Set:");Set<String> javaDevFirstName = javaProgrammers.stream().map(Person::getFirstName).collect(toSet());System.out.println(javaDevFirstName); //[Elsdon, Shawn, Palmer, Addison, Maude, Floyd, Vere, Tamsen, Jayden, Sindy] System.out.println("將 Java programmers 的 last name 存放到 TreeSet:");TreeSet<String> javaDevLastName = javaProgrammers.stream().map(Person::getLastName).collect(toCollection(TreeSet::new));System.out.println(javaDevLastName); //[Brittany, Corrina, Dene, Donny, Hervey, Jaimie, Jaycob, Jonie, Pam, Randall] View Code4.6 使用parallelStream方法
當(dāng)需要為多核系統(tǒng)優(yōu)化時(shí),可以 parallelStream().forEach(),只是此時(shí)原有元素的次序沒(méi)法保證,并行的情況下將改變串行時(shí)操作的行為:
System.out.println("計(jì)算付給 Java programmers 的所有money:");int totalSalary = javaProgrammers.parallelStream().mapToInt(p -> p.getSalary()).sum(); View Code4.7 使用summaryStatistics方法
使用summaryStatistics方法獲得stream 中元素的各種匯總數(shù)據(jù):
//計(jì)算 count, min, max, sum, and average for numbersList<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();System.out.println("List中最大的數(shù)字 : " + stats.getMax());System.out.println("List中最小的數(shù)字 : " + stats.getMin());System.out.println("所有數(shù)字的總和 : " + stats.getSum());System.out.println("所有數(shù)字的平均值 : " + stats.getAverage()); View Code?
參考
[1] 深入淺出 Java 8 Lambda 表達(dá)式
[2] Java中Lambda表達(dá)式的使用
[3] Java 8 中的 Streams API 詳解
[4] Lambda 表達(dá)式講解
?
總結(jié)
以上是生活随笔為你收集整理的Lambda表达式常用代码示例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Spark- Checkpoint原理剖
- 下一篇: 检测数据类型的几种方式