http://blog.csdn.net/goldenfish1919/article/details/11780751
原文:http://www.techempower.com/blog/2013/03/26/everything-about-java-8/
1.接口增強(qiáng)
(1)接口可以定義static方法
java.util.Comparator:
public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
return (Comparator<T>)Comparators.NaturalOrderComparator.INSTANCE;
}
(2)接口可以有default方法
java.lang.Iterable:
public default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default方法不能夠override:toString()、equals()、hashCode()方法。
An interface cannot provide a default implementation for any of the methods of the Object class。
接口不能夠提供Object類里面的方法的default實(shí)現(xiàn)。
ps:接口看上去越來越像抽象類了。
2.Functional接口
一個(gè)接口只定義了一個(gè)abstract方法,這個(gè)接口就是“functional接口”,比如:java.lang.Runnable。
“functional接口”中可以定義default方法
新引入@FunctionalInterface來標(biāo)記
3.Lambdas表達(dá)式
functional接口可以用Lambdas來實(shí)例化。
(int x, int y) -> { return x + y; } :兩個(gè)入?yún)ⅲ粋€(gè)返回值
(x, y) -> x + y:兩個(gè)入?yún)ⅲ粋€(gè)返回值,自動(dòng)推斷類型
x -> x * x:一個(gè)入?yún)ⅲ粋€(gè)返回值,自動(dòng)推斷類型
() -> x:沒有入?yún)ⅲ粋€(gè)返回值
x -> { System.out.println(x); }:一個(gè)入?yún)ⅲ瑳]有返回值,自動(dòng)推斷類型
String::valueOf static方法引用
Object::toString 非static方法引用
x::toString Capturing method reference
ArrayList::new 構(gòu)造函數(shù)引用
以下是等價(jià)的:
方法引用 等價(jià)的Lambdas表達(dá)式
String::valueOf x -> String.valueOf(x)
Object::toString x -> x.toString()
x::toString () -> x.toString()
ArrayList::new () -> new ArrayList<>()
ps:看到String::valueOf這種引用方式,不僅讓人想起了C++。
如果Lambdas表達(dá)式和“functional接口”外形相似,二者就可以兼容:
Comparator<String> c = (a, b) -> Integer.compare(a.length(),b.length());
Comparator類的compare()方法接收兩個(gè)String的入?yún)ⅲ祷匾粋€(gè)int,跟右邊的Lambdas表達(dá)式兼容。
所謂的外形相似就是說:入?yún)ⅰ⒎祷亍hecked異常。
Runnable r = () -> { System.out.println("Running!"); }也是ok的。
Capturing 與 non-capturing lambdas
如果一個(gè)Lambdas表達(dá)式訪問了{(lán)}范圍以外的非static的變量或者對(duì)象,那就是個(gè)Capturing Lambdas表達(dá)式:
int x = 5;
return y -> x + y;
Lambdas表達(dá)式captures了變量x,x必須得是“final等效”的:要么是final的,要么沒有被修改過。
是否是Capturing Lambdas與性能有關(guān),non-capturing的性能更高,non-capturing只需要被evaluated一次,只有一個(gè)instance,
但是,每次遇到Capturing lambdas都會(huì)evaluated,類似于匿名內(nèi)部類的實(shí)例化。
3.新添加包:java.util.function
這個(gè)包下面添加了很多functional接口:
Function<T, R> - take a T as input, return an R as ouput
Predicate<T> - take a T as input, return a boolean as output
Consumer<T> - take a T as input, perform some action and don't return anything
Supplier<T> - with nothing as input, return a T
BinaryOperator<T> - take two T's as input, return one T as output, useful for "reduce" operations
新添加了對(duì)應(yīng)基本數(shù)據(jù)類型的功能函數(shù)類,比如:
IntConsumer接收int,無返回,主要是為了性能的原因,避免自動(dòng)拆裝箱。
4.新添加包:java.util.stream
java.util.stream這個(gè)包主要是為了support functional-style operations on streams of value。
常見的獲取stream的方式是從Collection獲取:
Stream<T> stream = collection.stream();
一個(gè)stream就類似于是一個(gè)Iterator,只能遍歷一次,當(dāng)然stream也可能是無窮的。
stream可能是串行的也可能是并行的。
stream能做什么呢?
int sumOfWeights = blocks.stream().filter(b -> b.getColor() == RED)
.mapToInt(b -> b.getWeight())
.sum();
以上使用了簡(jiǎn)單類型的stream,sum()方法只有在簡(jiǎn)單類型的stream上才有。
stream提供了api用來轉(zhuǎn)換value,或者是對(duì)結(jié)果做一些操作,對(duì)stream的操作可以是“中間操作”也可能是“終止操作”。
中間操作:會(huì)保持stream處于打開的狀態(tài),并允許進(jìn)一步的操作,上例中的filter()和mapToInt()就是中間操作,返回的還是當(dāng)前的stream,允許更多的鏈?zhǔn)讲僮鳌?br /> 終止操作:必須是stream上的最后一個(gè)操作,一旦被調(diào)用,stream就被消費(fèi)掉,而且不能再使用了。
一般來說,對(duì)stream的處理包含三個(gè)步驟:
(1)從源處獲取stream
(2)做一個(gè)或多個(gè)中間操作
(3)做一個(gè)終止操作
Stream可以是有狀態(tài)(Stateful)的。
stream是可以短路操作(Short-circuiting)的,比如在處理無窮的stream的時(shí)候就需要提前停止。
stream的api方法介紹:
中間操作:
filter:排除掉所有不滿足預(yù)定條件的元素
map :使用Function對(duì)元素做一對(duì)一的轉(zhuǎn)換
flatMap :把一個(gè)元素映射成0個(gè)或者多個(gè)元素
distinct :根據(jù)equals方法,排除掉所有的重復(fù)元素,這是個(gè)stateful的操作。
sorted :讓元素有序,stateful
limit :讓后續(xù)的操作只能看到最多l(xiāng)imit個(gè)元素,stateful并且short-circuiting
substream :讓后續(xù)的操作只能看到stream的一部分。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave");
List<String> filteredNames = names.stream().filter(e -> e.length() >= 4).collect(Collectors.toList());
for (String name : filteredNames) {
System.out.println(name); //Alice Charlie Dave
}
終止操作:
forEach :對(duì)stream的每一個(gè)元素做一些處理
toArray :把元素導(dǎo)出到數(shù)組里面
reduce :使用BinaryOperator,把多個(gè)stream組合成一個(gè)
collect :把元素導(dǎo)出到某個(gè)容器里面,比如:collection或者map
min,max ,count ,
anyMatch :是否至少一個(gè)匹配的元素,short-circuiting。
allMatch :是否所有的元素都匹配,short-circuiting。
noneMatch :是否所有的元素都不匹配,short-circuiting。
findFirst :找到第一個(gè)匹配的元素,hort-circuiting。
findAny :找到任何一個(gè)匹配的元素,hort-circuiting。
中間操作是延遲(lazy)的。只有終止操作才會(huì)觸發(fā)對(duì)stream的處理。在終止操作開始的時(shí)候,無論有多少中間操作,
the elements are then consumed in (usually, but not quite always) a single pass.所有的元素都是進(jìn)行一次性處理,
有些Stateful操作(sorted(),distinct())可能會(huì)進(jìn)行第二次處理。
有專門針對(duì)基本類型的stream:IntStream,LongStream,DoubleStream
List<String> strings = Arrays.asList("hello", "java", "");
Object[] list = strings.stream() // Stream<String>
.mapToInt(String::length) // IntStream
.mapToLong(x -> Long.valueOf(x)) // LongStream
.mapToDouble(x -> x * 2.0) // DoubleStream
.boxed() // Stream<Double>
.toArray();
System.out.println(java.util.Arrays.toString(list));//[10.0, 8.0, 0.0]
5.泛型類型推斷增強(qiáng)
java7里面:
foo(Utility.<Type>bar());
Utility.<Type>foo().bar();
但是java8里面:
foo(Utility.bar());
Utility.foo().bar();
6.新引入java.time包
LocalDateTime:日期+時(shí)間
LocalDate:日期
LocalTime:時(shí)間
Instant:類似于java.util.Date
DateTimeFormatter:與字符串的轉(zhuǎn)化
與老的api轉(zhuǎn)化:
Date.toInstant()
Date.from(Instant)
Calendar.toInstant()
7.新添加了Collections API
Iterable.forEach(Consumer)
Iterator.forEachRemaining(Consumer)
Collection.removeIf(Predicate)
Collection.spliterator()
Collection.stream()
Collection.parallelStream()
List.sort(Comparator)
List.replaceAll(UnaryOperator)
Map.forEach(BiConsumer)
Map.replaceAll(BiFunction)
Map.putIfAbsent(K, V)
Map.remove(Object, Object)
Map.replace(K, V, V)
Map.replace(K, V)
Map.computeIfAbsent(K, Function)
Map.computeIfPresent(K, BiFunction)
Map.compute(K, BiFunction)
Map.merge(K, V, BiFunction)
Map.getOrDefault(Object, V)
List<String> strings = Arrays.asList("a", "b", "c");
// Index strings by length:
Map<Integer, List<String>> map = new HashMap<>();
for (String s : strings) {
map.computeIfAbsent(s.length(),key -> new ArrayList<String>()).add(s);
}
System.out.println(map);//{1=[a, b, c]}
把stram里面的元素放到colection或者map里面:
List<String> strings = Arrays.asList("a", "b", "c","hello","world");
// Although in this case the stream API may be a better choice:
Map<Integer, List<String>> map = strings.stream().collect(Collectors.groupingBy(String::length));
System.out.println(map);//{1=[a, b, c], 5=[hello, world]}
8.新添加了Concurrency API
ConcurrentHashMap被完全重寫
9.新添加了Concurrency API
10.反射和注解增強(qiáng)
注解可以加在泛型參數(shù)上: List<@Nullable String>
11.Nashorn JavaScript Engine
12.其他的一些api:
Base64
StringJoiner
Objects.isNull(Object)
Objects.nonNull(Object)
ThreadLocal<List<String>> strings = ThreadLocal.withInital(ArrayList::new);
people.sort(
Comparator.comparing(Person::getLastName)
.thenComparing(Person::getFirstName)
.thenComparing(
Person::getEmailAddress,
Comparator.nullsLast()
.thenComparing(String.CASE_INSENSITIVE_ORDER)));
總之一句話,加入了lambda表達(dá)式的java越來越像動(dòng)態(tài)語言了,源碼也越來越看不懂了,估計(jì)得好好的適應(yīng)一段時(shí)間了。
1.接口增強(qiáng)
(1)接口可以定義static方法
java.util.Comparator:
public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
return (Comparator<T>)Comparators.NaturalOrderComparator.INSTANCE;
}
(2)接口可以有default方法
java.lang.Iterable:
public default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default方法不能夠override:toString()、equals()、hashCode()方法。
An interface cannot provide a default implementation for any of the methods of the Object class。
接口不能夠提供Object類里面的方法的default實(shí)現(xiàn)。
ps:接口看上去越來越像抽象類了。
2.Functional接口
一個(gè)接口只定義了一個(gè)abstract方法,這個(gè)接口就是“functional接口”,比如:java.lang.Runnable。
“functional接口”中可以定義default方法
新引入@FunctionalInterface來標(biāo)記
3.Lambdas表達(dá)式
functional接口可以用Lambdas來實(shí)例化。
(int x, int y) -> { return x + y; } :兩個(gè)入?yún)ⅲ粋€(gè)返回值
(x, y) -> x + y:兩個(gè)入?yún)ⅲ粋€(gè)返回值,自動(dòng)推斷類型
x -> x * x:一個(gè)入?yún)ⅲ粋€(gè)返回值,自動(dòng)推斷類型
() -> x:沒有入?yún)ⅲ粋€(gè)返回值
x -> { System.out.println(x); }:一個(gè)入?yún)ⅲ瑳]有返回值,自動(dòng)推斷類型
String::valueOf static方法引用
Object::toString 非static方法引用
x::toString Capturing method reference
ArrayList::new 構(gòu)造函數(shù)引用
以下是等價(jià)的:
方法引用 等價(jià)的Lambdas表達(dá)式
String::valueOf x -> String.valueOf(x)
Object::toString x -> x.toString()
x::toString () -> x.toString()
ArrayList::new () -> new ArrayList<>()
ps:看到String::valueOf這種引用方式,不僅讓人想起了C++。
如果Lambdas表達(dá)式和“functional接口”外形相似,二者就可以兼容:
Comparator<String> c = (a, b) -> Integer.compare(a.length(),b.length());
Comparator類的compare()方法接收兩個(gè)String的入?yún)ⅲ祷匾粋€(gè)int,跟右邊的Lambdas表達(dá)式兼容。
所謂的外形相似就是說:入?yún)ⅰ⒎祷亍hecked異常。
Runnable r = () -> { System.out.println("Running!"); }也是ok的。
Capturing 與 non-capturing lambdas
如果一個(gè)Lambdas表達(dá)式訪問了{(lán)}范圍以外的非static的變量或者對(duì)象,那就是個(gè)Capturing Lambdas表達(dá)式:
int x = 5;
return y -> x + y;
Lambdas表達(dá)式captures了變量x,x必須得是“final等效”的:要么是final的,要么沒有被修改過。
是否是Capturing Lambdas與性能有關(guān),non-capturing的性能更高,non-capturing只需要被evaluated一次,只有一個(gè)instance,
但是,每次遇到Capturing lambdas都會(huì)evaluated,類似于匿名內(nèi)部類的實(shí)例化。
3.新添加包:java.util.function
這個(gè)包下面添加了很多functional接口:
Function<T, R> - take a T as input, return an R as ouput
Predicate<T> - take a T as input, return a boolean as output
Consumer<T> - take a T as input, perform some action and don't return anything
Supplier<T> - with nothing as input, return a T
BinaryOperator<T> - take two T's as input, return one T as output, useful for "reduce" operations
新添加了對(duì)應(yīng)基本數(shù)據(jù)類型的功能函數(shù)類,比如:
IntConsumer接收int,無返回,主要是為了性能的原因,避免自動(dòng)拆裝箱。
4.新添加包:java.util.stream
java.util.stream這個(gè)包主要是為了support functional-style operations on streams of value。
常見的獲取stream的方式是從Collection獲取:
Stream<T> stream = collection.stream();
一個(gè)stream就類似于是一個(gè)Iterator,只能遍歷一次,當(dāng)然stream也可能是無窮的。
stream可能是串行的也可能是并行的。
stream能做什么呢?
int sumOfWeights = blocks.stream().filter(b -> b.getColor() == RED)
.mapToInt(b -> b.getWeight())
.sum();
以上使用了簡(jiǎn)單類型的stream,sum()方法只有在簡(jiǎn)單類型的stream上才有。
stream提供了api用來轉(zhuǎn)換value,或者是對(duì)結(jié)果做一些操作,對(duì)stream的操作可以是“中間操作”也可能是“終止操作”。
中間操作:會(huì)保持stream處于打開的狀態(tài),并允許進(jìn)一步的操作,上例中的filter()和mapToInt()就是中間操作,返回的還是當(dāng)前的stream,允許更多的鏈?zhǔn)讲僮鳌?br /> 終止操作:必須是stream上的最后一個(gè)操作,一旦被調(diào)用,stream就被消費(fèi)掉,而且不能再使用了。
一般來說,對(duì)stream的處理包含三個(gè)步驟:
(1)從源處獲取stream
(2)做一個(gè)或多個(gè)中間操作
(3)做一個(gè)終止操作
Stream可以是有狀態(tài)(Stateful)的。
stream是可以短路操作(Short-circuiting)的,比如在處理無窮的stream的時(shí)候就需要提前停止。
stream的api方法介紹:
中間操作:
filter:排除掉所有不滿足預(yù)定條件的元素
map :使用Function對(duì)元素做一對(duì)一的轉(zhuǎn)換
flatMap :把一個(gè)元素映射成0個(gè)或者多個(gè)元素
distinct :根據(jù)equals方法,排除掉所有的重復(fù)元素,這是個(gè)stateful的操作。
sorted :讓元素有序,stateful
limit :讓后續(xù)的操作只能看到最多l(xiāng)imit個(gè)元素,stateful并且short-circuiting
substream :讓后續(xù)的操作只能看到stream的一部分。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave");
List<String> filteredNames = names.stream().filter(e -> e.length() >= 4).collect(Collectors.toList());
for (String name : filteredNames) {
System.out.println(name); //Alice Charlie Dave
}
終止操作:
forEach :對(duì)stream的每一個(gè)元素做一些處理
toArray :把元素導(dǎo)出到數(shù)組里面
reduce :使用BinaryOperator,把多個(gè)stream組合成一個(gè)
collect :把元素導(dǎo)出到某個(gè)容器里面,比如:collection或者map
min,max ,count ,
anyMatch :是否至少一個(gè)匹配的元素,short-circuiting。
allMatch :是否所有的元素都匹配,short-circuiting。
noneMatch :是否所有的元素都不匹配,short-circuiting。
findFirst :找到第一個(gè)匹配的元素,hort-circuiting。
findAny :找到任何一個(gè)匹配的元素,hort-circuiting。
中間操作是延遲(lazy)的。只有終止操作才會(huì)觸發(fā)對(duì)stream的處理。在終止操作開始的時(shí)候,無論有多少中間操作,
the elements are then consumed in (usually, but not quite always) a single pass.所有的元素都是進(jìn)行一次性處理,
有些Stateful操作(sorted(),distinct())可能會(huì)進(jìn)行第二次處理。
有專門針對(duì)基本類型的stream:IntStream,LongStream,DoubleStream
List<String> strings = Arrays.asList("hello", "java", "");
Object[] list = strings.stream() // Stream<String>
.mapToInt(String::length) // IntStream
.mapToLong(x -> Long.valueOf(x)) // LongStream
.mapToDouble(x -> x * 2.0) // DoubleStream
.boxed() // Stream<Double>
.toArray();
System.out.println(java.util.Arrays.toString(list));//[10.0, 8.0, 0.0]
5.泛型類型推斷增強(qiáng)
java7里面:
foo(Utility.<Type>bar());
Utility.<Type>foo().bar();
但是java8里面:
foo(Utility.bar());
Utility.foo().bar();
6.新引入java.time包
LocalDateTime:日期+時(shí)間
LocalDate:日期
LocalTime:時(shí)間
Instant:類似于java.util.Date
DateTimeFormatter:與字符串的轉(zhuǎn)化
與老的api轉(zhuǎn)化:
Date.toInstant()
Date.from(Instant)
Calendar.toInstant()
7.新添加了Collections API
Iterable.forEach(Consumer)
Iterator.forEachRemaining(Consumer)
Collection.removeIf(Predicate)
Collection.spliterator()
Collection.stream()
Collection.parallelStream()
List.sort(Comparator)
List.replaceAll(UnaryOperator)
Map.forEach(BiConsumer)
Map.replaceAll(BiFunction)
Map.putIfAbsent(K, V)
Map.remove(Object, Object)
Map.replace(K, V, V)
Map.replace(K, V)
Map.computeIfAbsent(K, Function)
Map.computeIfPresent(K, BiFunction)
Map.compute(K, BiFunction)
Map.merge(K, V, BiFunction)
Map.getOrDefault(Object, V)
List<String> strings = Arrays.asList("a", "b", "c");
// Index strings by length:
Map<Integer, List<String>> map = new HashMap<>();
for (String s : strings) {
map.computeIfAbsent(s.length(),key -> new ArrayList<String>()).add(s);
}
System.out.println(map);//{1=[a, b, c]}
把stram里面的元素放到colection或者map里面:
List<String> strings = Arrays.asList("a", "b", "c","hello","world");
// Although in this case the stream API may be a better choice:
Map<Integer, List<String>> map = strings.stream().collect(Collectors.groupingBy(String::length));
System.out.println(map);//{1=[a, b, c], 5=[hello, world]}
8.新添加了Concurrency API
ConcurrentHashMap被完全重寫
9.新添加了Concurrency API
10.反射和注解增強(qiáng)
注解可以加在泛型參數(shù)上: List<@Nullable String>
11.Nashorn JavaScript Engine
12.其他的一些api:
Base64
StringJoiner
Objects.isNull(Object)
Objects.nonNull(Object)
ThreadLocal<List<String>> strings = ThreadLocal.withInital(ArrayList::new);
people.sort(
Comparator.comparing(Person::getLastName)
.thenComparing(Person::getFirstName)
.thenComparing(
Person::getEmailAddress,
Comparator.nullsLast()
.thenComparing(String.CASE_INSENSITIVE_ORDER)));
總之一句話,加入了lambda表達(dá)式的java越來越像動(dòng)態(tài)語言了,源碼也越來越看不懂了,估計(jì)得好好的適應(yīng)一段時(shí)間了。