Java Version-wise Features History
Java 8 Lambda Expressions Tutorial
lambda表达式对应的就是函数式接口
所以首先来了解下函数式接口:functional interface
functional interface 又被叫做:Single Abstract Method interfaces (SAM Interfaces)
只有一个抽象方法的接口(接口里的方法默认就是抽象的abstract)
备注:该接口还可以包含default方法,static方法及Object类的public方法。
比如Java类中的Runnable 接口 和 Comparable接口:
public interface Runnable {
public abstract void run();
}
------------------------------------------
public interface Comparable<T> {
public int compareTo(T o);
}
或者自己定义的(@FunctionalInterface 注解可有可无)
@FunctionalInterface
public interface MyFirstFunctionalInterface {
public void firstWork();
}
完整实例:
interface MathOperation {//@FunctionalInterface
// 只有count这一个方法,可以加修饰符abstract也可以不加
int count(int i,int b) throws Exception;
//一下三个都是Object中pulibc 方法
String toString(); //same to Object.toString
int hashCode(); //same to Object.hashCode
boolean equals(Object obj); //same to Object.equals
// clone 的修饰符是protected 加上这个就不是函数式接口了
// Object clone(); 。
// 默认方法,可以有多个
default int ss(int a,int b){
return a-b;
};
// static 方法
static int identity(int s) {
return s-1;
}
}
错误提示:
Invalid '@FunctionalInterface' annotation; LambdaTest.MyFirstFunctionalInterface is not a functional interface
有@FunctionalInterface注解,但不符合函数式接口定义就会提示该错误
@FunctionalInterface
public interface MyFirstFunctionalInterface {
public void firstWork();
public void doSomeMoreWork();
}
函数式接口总结:
1,只有一个抽象方法。如果有多个抽象方法则不是函数式接口。
2,@FunctionalInterface 注解是可有可无的。
3,函数式接口可以添加任意的default methods ,as many as you like。因为默认方法不是抽象的方法
4,在函数式接口中可以重写Object的public 方法
有了函数式接口的概念,就可以开始Lambda表达式了
lambda表达式就是一个匿名函数。
lambda表达式对应的逻辑操作等同于函数式接口的那个抽象方法的实现。
语法:
(parameters) -> expression
(parameters) -> { statements; }
() -> expression
eg:
(int a, int b) -> a * b
// takes two integers and returns their multiplication(乘法)
(a, b) -> a - b
// takes two numbers and returns their difference
() -> 99
// takes no values and returns 99
(String a) -> System.out.println(a)
// takes a string, prints its value to the console, and returns nothing
a -> 2 * a
// takes a number and returns the result of doubling it
c -> { //some complex statements }
// takes a collection and do some procesing
解释说明:
1,lamdba expression 可以有0个或者多个参数
2,参数可以是java类型或者是通过上下文推断。
3,多个参数通过()闭合,()表示空的参数。
4,只有一个参数的时候,如果参数时推断类型,则不需要() . eg:a -> return a*a.
5,lambda expression 的body,可以有0个多个语句。
6,body是单个语句可以不用{}闭合。多个语句则必须使用{}闭合.
一些简单的列子:
1,
new Thread( ()->System.out.println(" thread run ") ).start();
2,循环遍历-迭代
List<String> ss = new ArrayList<String>();
ss.add("1");ss.add("2");ss.add("3");ss.add("4");ss.add("5");ss.add("6");
ss.forEach((s)->System.out.println(s+";"));
3,事件的监听
JButton button = new JButton("Submit");
button.addActionListener((e) -> {
System.out.println("Click event triggered !!");
});
4,排序
List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
/*Collections.sort(names, new Comparator<String>() {//java以前老版本的写法
@Override
public int compare(String a, String b) {
return b.compareTo(a);
}
});*/
Collections.sort(names,(a,b)-> b.compareTo(a));
names.forEach((s)-> {System.out.println("sort = "+s);});
输出结果:
thread run
1;
2;
3;
4;
5;
6;
sort = xenia
sort = peter
sort = mike
sort = anna
Method References: 方法调用,方法引用
有一些lambda表达式,就是调用一个bean对象的某一个方法。这个时候就可以使用 method references 。
例如:
//传进来是Person 返回结果是name
原始写法:
Comparator<Person> byName = Comparator.comparing(new Function<Person, String>() {
@Override
public String apply(Person t) {
return t.getName();
}
});
lambda 表达式
byName = Comparator.comparing(person -> person.getName());
method reerences 方法引用:
byName = Comparator.comparing(Person::getName);
如此的简洁明了,前提是你需要理解
一共有四种方法引用:
1,引用类的静态方法
2,引用一个实例方法
3,引用类的方法
4,引用类的构造方法
eg:
1,Reference to a Static Method
// 类的静态方法
Arrays.sort(ps, Person::compareByNameStatic);
2,Reference to an Instance Method of a Particular Object
// 对象的实例方法
Person personTest = new Person();
Arrays.sort(ps, personTest::compareByName);
3,Reference to an Instance Method of an Arbitrary Object of a Particular Type
// 类的方法
3.1
byName = Comparator.comparing(Person::getName);
3.2
String[] stringArray = { "Barbara", "James", "Mary", "John","Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);
4,Reference to a Constructor
引用构造方法:
personTest.getHashSet(HashSet::new);
Person类中:
public HashSet getHashSet(HashCreate p){
return p.convert();
}
再定义一个函数式接口
interface HashCreate {
HashSet convert();
}
Default Methods :默认方法
1,添加默认方法
2,继承父类的
3,重写父类的
// 默认方法,可以有多个
default int ss(int a,int b){
return a-b;
};
Static Methods :静态方法
public interface TimeClient {
// ...
static public ZoneId getZoneId (String zoneString) {
try {
return ZoneId.of(zoneString);
} catch (DateTimeException e) {
System.err.println("Invalid time zone: " + zoneString +
"; using default time zone instead.");
return ZoneId.systemDefault();
}
}
default public ZonedDateTime getZonedDateTime(String zoneString) {
return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
}
}
java 8 新增api和已存在api的增强
1,java.util 中添加了java.lang.invoke包,streams也集成到了集合框架,集合框架中的方法也可以被steams调用
2,java.util.function 新增的包,提供lambda expression 目标类型和方法引用
3,java.util.stream 新增的包,提供streams方法和集合操作
最后附上被修改的包:
Package | New Classes | Modified Classes |
java.io | UncheckedIOException | BufferedReader |
not applicable | AutoCloseable ThreadLocal String Iterable CharSequence Boolean Integer Long Float Double | |
java.nio.file | not applicable | Files |
java.util | PrimitiveIterator Spliterator DoubleSummaryStatistics IntSummaryStatistics LongSummaryStatistics Optional OptionalDouble OptionalInt OptionalLong Spliterators SplittableRandom StringJoiner | Arrays BitSet Collection Comparator Iterator List Map Map.Entry LinkedHashMap Random TreeMap |
java.util.concurrent | not applicable | ThreadLocalRandom |
java.util.jar | not applicable | JarFile |
java.util.zip | not applicable | ZipFile |
java.util.logging | not applicable | Logger |
java.util.regex | not applicable | Pattern |