1. 程式人生 > >java8新特性 (λ、stream 與 預設介面方法)

java8新特性 (λ、stream 與 預設介面方法)

1.lambda

λ表示式本質上是一個匿名方法,用來方便地實現函式介面。也就是說,λ表示式主要用於替換以前廣泛使用的內部匿名類。 
讓我們來看下面這個例子:
    public int add(int x, int y) {
        return x + y;
    }
轉成λ表示式後是這個樣子:
    (int x, int y) -> x + y;
引數型別也可以省略,Java編譯器會根據上下文推斷出來:
    (x, y) -> x + y; //返回兩數之和
或者
    (x, y) -> { return x + y; } //顯式指明返回值

λ表示式由三部分組成:引數列表

箭頭(->),以及一個表示式或語句塊

λ表示式的型別,叫做“目標型別(target type)。λ表示式的目標型別是“函式介面(functional interface),這是Java8新引入的概念。它的定義是:一個介面,如果只有一個顯式宣告的抽象方法,那麼它就是一個函式介面。一般用@FunctionalInterface標註出來(也可以不標)。舉例如下:
public interface Runnable { void run(); }
public interface Comparator<T> { int compare(T o1, T o2);}

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class A {
	public int a = 10;

	public static void main(String[] args) {
		List namesList = Arrays.asList("peter", "anna", "mike",
				"xenia", "xiaoMing");
		Collections.sort(namesList, (a, b) -> (a.length() - b.length()));
		System.out.println(namesList);
		namesList.forEach((o) -> {
			System.out.println(o);
		});

		System.out.println();
		new Thread(() -> {
			System.out.println("Hello Lambda!");
		}).start();

		//anonymous class
		Thread oldSchool = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println("This is from an anonymous class.");
			}
		});
		oldSchool.start();
	}
}
/*
 * [anna, mike, peter, xenia, xiaoMing] anna mike peter xenia xiaoMing
 * 
 * Hello Lambda! This is from an anonymous class.
 */
lambda不是匿名內部類的語法糖,見下。
package com.yichudu;

public class A {
	public static void main(String[] args) {
		//使用匿名內部類,編譯後會有A$1.class的存在
		Thread t1=new Thread(new Runnable() {
			
			@Override
			public void run() {
				System.out.print(123);
				
			}
		} );
		//use lambda expression,no extra class generates.
		Thread t2=new Thread(()->{System.out.print(123);});
	}
}


2.stream

Stream<E> java.util.Collection.stream()
返回Stream物件。
Stream<T> java.util.stream.Stream.filter(Predicate<? super T> predicate)
從stream中過濾元素,返回的stream由與謂詞匹配的元素組成。
void java.util.stream.Stream.forEach(Consumer<? super T> action)
對stream中的每一個元素執行action。 boolean java.util.function.Predicate.test(T t)
Predicate介面中的方法,評估給定元素是否滿足謂詞。 void java.util.function.Consumer.accept(T t)
Consumer介面中的方法,此方法對給定的元素進行操作。
public class Apple {
	public int weight = 2;
	public Apple(){}
	public Apple(int x){
		weight=x;
	}
	public static void main(String[] args) {
		List fruits = Arrays.asList(new Apple(), new Apple(),new Apple(3));
		//過濾出重量為2的蘋果,並將這些蘋果重量設為1
		fruits.stream().filter(s -> s.weight == 2).forEach(s -> s.weight = 1);
		//得到最沉的蘋果
		Apple heaviestApple=fruits.stream().max((a,b)->(a.weight-b.weight)).get();
		heaviestApple.weight=4;
		//求出所有蘋果的重量之和
		int sum=fruits.stream().mapToInt(o->o.weight).sum();
		//輸出驗證
		fruits.forEach(o -> System.out.print(o.weight));
	}
}
// 114

3.預設介面方法

通過default關鍵字給介面的方法提供預設實現。 這樣與抽象類的普通方法就差別不大了。 java.util.Collection介面的原始碼含有下面的預設介面實現。
  default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }