2019独角兽企业重金招聘Python工程师标准>>>
今天仔细的看了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 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 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 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 roster, Predicate tester) {
for (Person p : roster) {
if (tester.test(p)) {
p.printPerson();
}
}
}
// Approach 7: Use Lambda Expressions Throughout Your Application
public static void processPersons(
List roster,
Predicate tester,
Consumer block) {
for (Person p : roster) {
if (tester.test(p)) {
block.accept(p);
}
}
}
// Approach 7, second example
public static void processPersonsWithFunction(
List roster,
Predicate tester,
Function mapper,
Consumer 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 void processElements(
Iterable source,
Predicate tester,
Function mapper,
Consumer block) {
for (X p : source) {
if (tester.test(p)) {
Y data = mapper.apply(p);
block.accept(data);
}
}
}
class PersonAgeComparator implements Comparator {
public int compare(Person a, Person b) {
return a.getBirthday().compareTo(b.getBirthday());
}
}
public static void main(String... args) {
List 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 createRoster() {
List 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 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 myConsumer2 = new Consumer(){
@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);
}
}