java8新特性之——lambda表達式的使用

lambda表達式簡介

我的理解,lambda表達式就是一種新的語法,沒有什麼新奇的,簡化了開發者的編碼,其實底層仍是一些常規的代碼。Lambda 是一個匿名函數,咱們能夠把 Lambda 表達式理解爲是一段能夠傳遞的代碼(將代碼像數據同樣進行傳遞)。能夠寫出更簡潔、更靈活的代碼。做爲一種更緊湊的代碼風格,使Java的語言表達能力獲得了提高。html

Lambda表達式的語法(記得要在jdk1.8及以上的jdk環境下實驗)

Lambda 表達式的基礎語法:Java8中引入了一個新的操做符 "->" 該操做符稱爲箭頭操做符或 Lambda 操做符
箭頭操做符將 Lambda 表達式拆分紅兩部分:
左側:Lambda 表達式的參數列表
右側:Lambda 表達式中所需執行的功能, 即 Lambda 體
java

語法格式一:無參數,無返回值

示例:app

//平時的寫法
@Test
	public void test1() {
		Runnable runnable = new Runnable() {
			
			@Override
			public void run() {
		System.out.println("線程啓動了");		
			}
		};
		runnable.run();
	}
  /**
   * 語法格式一:無參數,無返回值
   * 		() -> System.out.println("Hello Lambda!");
   */
	@Test
	public void test2() {
		//「->」左邊只有一個小括號,表示無參數,右邊是Lambda體(就至關於實現了匿名內部類裏面的方法了,(即就是一個可用的接口實現類了。))
	Runnable runnable = ()->System.out.println("線程啓動了");	
	runnable.run();
	}

運行結果
jvm

語法格式二:有一個參數,而且無返回值

(x) -> System.out.println(x)

示例:ide

/**語法格式二:有一個參數,而且無返回值
	 * 		(x) -> System.out.println(x)
	 */
	@Test
	public void test3() {
          //這個e就表明所實現的接口的方法的參數,
	   Consumer<String> consumer = e->System.out.println("ghijhkhi"+e);
	   consumer.accept("woojopj");
	}

Consumer的底層實現:函數

/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package java.util.function;

import java.util.Objects;

/**
 * Represents an operation that accepts a single input argument and returns no
 * result. Unlike most other functional interfaces, {@code Consumer} is expected
 * to operate via side-effects.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #accept(Object)}.
 *
 * @param <T> the type of the input to the operation
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);

    /**
     * Returns a composed {@code Consumer} that performs, in sequence, this
     * operation followed by the {@code after} operation. If performing either
     * operation throws an exception, it is relayed to the caller of the
     * composed operation.  If performing this operation throws an exception,
     * the {@code after} operation will not be performed.
     *
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

結果:ui

語法格式三:若只有一個參數,小括號能夠省略不寫 x -> System.out.println(x)</font(第二種方式的一種簡化吧)

語法格式四:有兩個以上的參數,有返回值,而且 Lambda 體中有多條語句

示例代碼:this

@Test
	public void test4() {
                //Lambda 體中有多條語句,記得要用大括號括起來
		Comparator<Integer> com = (x, y) -> {
		     			System.out.println("函數式接口");
		     			return Integer.compare(x, y);
		     		};
		     		int compare = com.compare(100, 244);
		     		System.out.println(compare);
			}

Comparator的底層相信你們都看過,是有一個compare()方法的。

運行結果:
編碼

語法格式五:若 Lambda 體中只有一條語句, return 和 大括號均可以省略不寫 即:Comparator com = (x, y) -> Integer.compare(x, y);

語法格式六:Lambda 表達式的參數列表的數據類型能夠省略不寫,由於JVM編譯器經過上下文推斷出,數據類型,即「類型推斷」(Integer x, Integer y) -> Integer.compare(x, y);

到這兒,相信你們也看出來規律了,這個Lambda表達式,好像離不開接口咦.......你還真說對了,這個Lambda表達式,是須要函數式接口的支持的,那麼什麼是函數式接口呢?
函數式接口 ,即只包含一個抽象方法的接口,稱爲函數式接口。
你能夠經過 Lambda 表達式來建立該接口的對象。(若 Lambda 表達式拋出一個受檢異常,那麼該異常須要在目標接口的抽象方法上進行聲明)。
咱們能夠在任意函數式接口上使用 @FunctionalInterface 註解,這樣作能夠檢查它是不是一個函數式接口,同時 javadoc 也會包含一條聲明,說明這個接口是一個函數式接口。像上面的Consumer接口就是一個函數式接口。
Java內置的四大函數式接口分別是:

consumer的上面已經演示過了。
下面是剩下的三個的線程

@Test
	public void test6() {
		Supplier<String> supplier = ()->"532323".substring(0, 2);
		System.out.println(supplier.get());
	}
	@Test
	public void test7() {
		Function<String, String> function = (x)->x.substring(0, 2);
		System.out.println(function.apply("我是中國人"));
	}
	@Test
	public void test8() {
		Predicate<String> predicate = (x)->x.length()>5;
		System.out.println(predicate.test("12345678"));
		System.out.println(predicate.test("123"));
	}

運行結果

方法引用與構造器引用

方法引用

當要傳遞給Lambda體的操做,已經有實現的方法了,可使用方法引用!
方法引用就是Lambda表達式,就是函數式接口的一個實例,經過方法的名字來指向一個方法,能夠認爲是Lambda表達式的一個語法糖。
要求:實現抽象方法的參數列表和返回值類型,必須與方法引用的方法的參數列表和返回值類型保持一致!
方法引用:使用操做符 「::」 將類(或對象) 與 方法名分隔開來。
以下三種主要使用狀況:
對象::實例方法名
類::靜態方法名
類::實例方法名

"實現抽象方法的參數列表和返回值類型,必須與方法引用的方法的參數列表和返回值類型保持一致" 這句話很重要,必定要理解
個人理解是:
舉個例子
Comparator comparator = (x,y)->Integer.compare(x, y);等同於
Comparator comparator1 = Integer::compare;
即:方法引用的方法是Integer的compare吧,他的參數列表是兩個integer類型,返回值是int,這個例子中的抽象方法是Comparator接口的compare()方法

public void test12() {
		Comparator<Integer> comparator = (x,y)->Integer.compare(x, y);
		Comparator<Integer> comparator1 = Integer::compare;
		int compare = comparator.compare(1, 2);
		int compare2 = comparator1.compare(1, 2);
		System.out.println("compare:"+compare);
		System.out.println("compare2:"+compare2);

	}

運行結果

compare:-1
compare2:-1
相關文章
相關標籤/搜索