今天仔细的看了java8 Lambda Expressions(lamba表达式) 官方样例代码,详见:http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html. 有兴趣的朋友可以看一下。
针对官方样例代码进行了部分整理,详细参见下面的源代码,供有兴趣的朋友学习。
此类从普通实现方式,接口实现方式,匿名类实现方式,lambda表达式实现方式逐步讲解为什么要引入lambda表达式,如果实现lambda表达式。
在文章最后,讲解了lambda表达式的捕获变量、类型推断、序列化方面的知识
package lambda; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; public class RosterTest { interface CheckPerson { boolean test(Person p); } // Approach 1: Create Methods that Search for Persons that Match One // Characteristic public static void printPersonsOlderThan(List<Person> roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } } // Approach 2: Create More Generalized Search Methods public static void printPersonsWithinAgeRange( List<Person> roster, int low, int high) { for (Person p : roster) { if (low <= p.getAge() && p.getAge() < high) { p.printPerson(); } } } // Approach 3: Specify Search Criteria Code in a Local Class // Approach 4: Specify Search Criteria Code in an Anonymous Class // Approach 5: Specify Search Criteria Code with a Lambda Expression public static void printPersons( List<Person> roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } } // Approach 6: Use Standard Functional Interfaces with Lambda Expressions public static void printPersonsWithPredicate( List<Person> roster, Predicate<Person> tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } } // Approach 7: Use Lambda Expressions Throughout Your Application public static void processPersons( List<Person> roster, Predicate<Person> tester, Consumer<Person> block) { for (Person p : roster) { if (tester.test(p)) { block.accept(p); } } } // Approach 7, second example public static void processPersonsWithFunction( List<Person> roster, Predicate<Person> tester, Function<Person, String> mapper, Consumer<String> block) { for (Person p : roster) { if (tester.test(p)) { String data = mapper.apply(p); block.accept(data); } } } // Approach 8: Use Generics More Extensively public static <X, Y> void processElements( Iterable<X> source, Predicate<X> tester, Function<X, Y> mapper, Consumer<Y> block) { for (X p : source) { if (tester.test(p)) { Y data = mapper.apply(p); block.accept(data); } } } class PersonAgeComparator implements Comparator<Person> { public int compare(Person a, Person b) { return a.getBirthday().compareTo(b.getBirthday()); } } public static void main(String... args) { List<Person> roster = Person.createRoster(); Person[] rosterAsArray = roster.toArray(new Person[roster.size()]); Arrays.sort(rosterAsArray, Person::compareByAge); for(Person p:rosterAsArray){ p.printPerson(); } for (Person p : roster) { p.printPerson(); } // Approach 1: Create Methods that Search for Persons that Match One // Characteristic System.out.println("Persons older than 20:"); printPersonsOlderThan(roster, 20); System.out.println(); // Approach 2: Create More Generalized Search Methods System.out.println("Persons between the ages of 14 and 30:"); printPersonsWithinAgeRange(roster, 14, 30); System.out.println(); // Approach 3: Specify Search Criteria Code in a Local Class System.out.println("Persons who are eligible for Selective Service:"); class CheckPersonEligibleForSelectiveService implements CheckPerson { public boolean test(Person p) { return p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25; } } printPersons( roster, new CheckPersonEligibleForSelectiveService()); System.out.println(); // Approach 4: Specify Search Criteria Code in an Anonymous Class System.out.println("Persons who are eligible for Selective Service " + "(anonymous class):"); printPersons( roster, new CheckPerson() { public boolean test(Person p) { return p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25; } } ); System.out.println(); // Approach 5: Specify Search Criteria Code with a Lambda Expression System.out.println("Persons who are eligible for Selective Service " + "(lambda expression):"); printPersons( roster, (Person p) -> p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25 ); System.out.println(); // Approach 6: Use Standard Functional Interfaces with Lambda // Expressions System.out.println("Persons who are eligible for Selective Service " + "(with Predicate parameter):"); printPersonsWithPredicate( roster, p -> p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25 ); System.out.println(); // Approach 7: Use Lamba Expressions Throughout Your Application System.out.println("Persons who are eligible for Selective Service " + "(with Predicate and Consumer parameters):"); processPersons( roster, p -> p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25, p -> p.printPerson() ); System.out.println(); // Approach 7, second example System.out.println("Persons who are eligible for Selective Service " + "(with Predicate, Function, and Consumer parameters):"); processPersonsWithFunction( roster, p -> p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25, p -> p.getEmailAddress(), email -> System.out.println(email) ); System.out.println(); // Approach 8: Use Generics More Extensively System.out.println("Persons who are eligible for Selective Service " + "(generic version):"); processElements( roster, p -> p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25, p -> p.getEmailAddress(), email -> System.out.println(email) ); System.out.println(); // Approach 9: Use Bulk Data Operations That Accept Lambda Expressions // as Parameters System.out.println("Persons who are eligible for Selective Service " + "(with bulk data operations):"); roster .stream() .filter( p -> p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25) .map(p -> p.getEmailAddress()) .forEach(email -> System.out.println(email)); } }
使用到的Person类源代码
package lambda; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; public class Person { String name; int age; LocalDate birthday; Sex gender; String emailAddress; public enum Sex { MALE, FEMALE } public Person(String name, int age, Sex gender, String emailAddress) { this.name = name; this.age = age; this.gender = gender; this.emailAddress = emailAddress; } public void printPerson() { System.out .println(name + "," + age + "," + gender + "," + emailAddress); } public static List<Person> createRoster() { List<Person> list = new ArrayList<>(); list.add(new Person("张三", 12, Sex.MALE, "[email protected]")); list.add(new Person("李四", 19, Sex.FEMALE, "[email protected]")); list.add(new Person("王五", 23, Sex.MALE, "[email protected]")); list.add(new Person("赵六", 36, Sex.FEMALE, "[email protected]")); list.add(new Person("蔡七", 12, Sex.MALE, "[email protected]")); return list; } public static int compareByAge(Person a, Person b) { return a.age > b.age ? 1 : a.age == b.age ? 0 : -1; } public String getName() { return name; } public void setName(String name) { this.name = name; } public LocalDate getBirthday() { return birthday; } public void setBirthday(LocalDate birthday) { this.birthday = birthday; } public Sex getGender() { return gender; } public void setGender(Sex gender) { this.gender = gender; } public String getEmailAddress() { return emailAddress; } public void setEmailAddress(String emailAddress) { this.emailAddress = emailAddress; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } }
使用多个参数的lamba表达式样例
package lambda; public class Calculator { interface IntegerMath { int operation(int a, int b); } public int operateBinary(int a, int b, IntegerMath op) { return op.operation(a, b); } public static void main(String... args) { Calculator myApp = new Calculator(); IntegerMath addition = (a, b) -> a + b; IntegerMath subtraction = (a, b) -> a - b; System.out.println("40 + 2 = " + myApp.operateBinary(40, 2, addition)); System.out.println("20 - 10 = " + myApp.operateBinary(20, 10, subtraction)); } }
lambda表达式变量范围的测试
package lambda; import java.util.function.Consumer; public class LambdaScopeTest { public int x = 0; class FirstLevel { public int x = 1; void methodInFirstLevel(int x) { // The following statement causes the compiler to generate // the error "local variables referenced from a lambda expression // must be final or effectively final" in statement A: // // x = 99; Consumer<Integer> myConsumer = (y) -> { System.out.println("x = " + x); // Statement A System.out.println("y = " + y); System.out.println("this.x = " + this.x); System.out.println("LambdaScopeTest.this.x = " + LambdaScopeTest.this.x); }; Consumer<Integer> myConsumer2 = new Consumer<Integer>(){ @Override public void accept(Integer x) { System.out.println("x = " + x); // Statement A System.out.println("x = " + x); System.out.println("this.x = " + FirstLevel.this.x); System.out.println("LambdaScopeTest.this.x = " + LambdaScopeTest.this.x); } }; myConsumer.accept(x); System.out.println("--------------"); myConsumer2.accept(x); } } public static void main(String... args) { LambdaScopeTest st = new LambdaScopeTest(); LambdaScopeTest.FirstLevel fl = st.new FirstLevel(); fl.methodInFirstLevel(23); } }