1. 程式人生 > >Java學習筆記--Java8新特性

Java學習筆記--Java8新特性

Lambda表示式

  • Lambda表示式的作用就是在代替冗長的匿名內部類,使用簡潔的方式重寫介面中的抽象方法,並建立子類物件。
  • Lambda表示式被"->"操作符分成兩部分,左側表示引數列表,右側表示所執行的功能。
  • Lambda表示式需要函式式介面的支援,即只有一個抽象方法的介面。抽象方法的引數以及返回值有不同的型別,所以Lambda的書寫方式也有所不同。
  • 語法格式一:無引數,無返回值
() -> System.out.println("Hello Lambda!");
  • 語法格式二:有一個引數,並且無返回值
(x) -> System.out.println(x)
  • 語法格式三:若只有一個引數,小括號可以省略不寫
x -> System.out.println(x)
  • 語法格式四:有兩個以上的引數,有返回值,並且 Lambda 體中有多條語句
Comparator<Integer> com = (x, y) -> {
	System.out.println("函式式介面");
	return Integer.compare(x, y);
};
  • 語法格式五:若 Lambda 體中只有一條語句, return 和 大括號都可以省略不寫
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
  • 語法格式六:Lambda 表示式的引數列表的資料型別可以省略不寫,因為JVM編譯器通過上下文推斷出資料型別,即“型別推斷”。
  • Java8內建了一些常用的函式式介面,專門為Lambda表示式提供服務,使用者不需要再額外建立介面。下面使用程式碼展示了四大核心函式式介面及其例項應用:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.
util.function.Predicate; import java.util.function.Supplier; /* * Java8 內建的四大核心函式式介面 * * Consumer<T> : 消費型介面 * void accept(T t); * * Supplier<T> : 供給型介面 * T get(); * * Function<T, R> : 函式型介面 * R apply(T t); * * Predicate<T> : 斷言型介面 * boolean test(T t); * */ public class TestLambda { public static void main(String[] args){ test1(); test2(); test3(); test4(); } //Predicate<T> 斷言型介面: private static void test4(){ List<String> list = Arrays.asList("Hello", "atguigu", "Lambda", "www", "ok"); List<String> strList = filterStr(list, (s) -> s.length() > 3); for (String str : strList) { System.out.println(str); } } //需求:將滿足條件的字串,放入集合中 private static List<String> filterStr(List<String> list, Predicate<String> pre){ List<String> strList = new ArrayList<>(); for (String str : list) { if(pre.test(str)){ strList.add(str); } } return strList; } //Function<T, R> 函式型介面: private static void test3(){ String newStr = strHandler("\t\t\t 我愛java ", (str) -> str.trim()); System.out.println(newStr); String subStr = strHandler("我愛java", (str) -> str.substring(2, 6)); System.out.println(subStr); } //需求:用於處理字串 private static String strHandler(String str, Function<String, String> fun){ return fun.apply(str); } //Supplier<T> 供給型介面 : private static void test2(){ List<Integer> numList = getNumList(10, () -> (int)(Math.random() * 100)); for (Integer num : numList) { System.out.println(num); } } //需求:產生指定個數的整數,並放入集合中 private static List<Integer> getNumList(int num, Supplier<Integer> sup){ List<Integer> list = new ArrayList<>(); for (int i = 0; i < num; i++) { Integer n = sup.get(); list.add(n); } return list; } //Consumer<T> 消費型介面 : private static void test1(){ happy(10000, (m) -> System.out.println("某人喜歡大寶劍,每次消費:" + m + "元")); } private static void happy(double money, Consumer<Double> con){ con.accept(money); } }

方法引用

  • Lambda表示式可以被方法引用、構造器引用和陣列引用進一步簡化。
import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

import org.junit.Test;

/*
 * 一、方法引用:若 Lambda 體中的功能,已經有方法提供了實現,可以使用方法引用
 * 			  (可以將方法引用理解為 Lambda 表示式的另外一種表現形式)
 * 
 * 1. 物件的引用 :: 例項方法名
 * 
 * 2. 類名 :: 靜態方法名
 * 
 * 3. 類名 :: 例項方法名
 * 
 * 注意:
 * 	 ①方法引用所引用的方法的引數列表與返回值型別,需要與函式式介面中抽象方法的引數列表和返回值型別保持一致!
 * 	 ②若Lambda的引數列表的第一個引數是例項方法的呼叫者,第二個引數(或無參)是例項方法的引數時,格式: ClassName::MethodName
 * 
 * 二、構造器引用 :構造器的引數列表,需要與函式式介面中引數列表保持一致!
 * 
 * 1. 類名 :: new
 * 
 * 三、陣列引用
 * 
 * 	型別[] :: new;
 * 
 * 
 */
public class TestMethodRef {
	//陣列引用
	@Test
	public void test8(){
		Function<Integer, String[]> fun = (args) -> new String[args];
		String[] strs = fun.apply(10);
		System.out.println(strs.length);
		
		System.out.println("--------------------------");
		
		Function<Integer, Employee[]> fun2 = Employee[] :: new;
		Employee[] emps = fun2.apply(20);
		System.out.println(emps.length);
	}
	
	//構造器引用
	@Test
	public void test7(){
	    //對應Employee類必須有帶參構造方法,且唯一引數型別為String
		Function<String, Employee> fun = Employee::new;
		//對應Employee類必須有帶參構造方法,且引數型別為String、int
		BiFunction<String, Integer, Employee> fun2 = Employee::new;
	}
	
	@Test
	public void test6(){
	    //對應Employee類的無參構造方法
		Supplier<Employee> sup = () -> new Employee();
		System.out.println(sup.get());
		
		System.out.println("------------------------------------");
		//對應Employee類的無參構造方法
		Supplier<Employee> sup2 = Employee::new;
		System.out.println(sup2.get());
	}
	
	//類名 :: 例項方法名
	@Test
	public void test5(){
		BiPredicate<String, String> bp = (x, y) -> x.equals(y);
		System.out.println(bp.test("abcde", "abcde"));
		
		System.out.println("-----------------------------------------");
		
		BiPredicate<String, String> bp2 = String::equals;
		System.out.println(bp2.test("abc", "abc"));
		
		System.out.println("-----------------------------------------");
		
		
		Function<Employee, String> fun = (e) -> e.show();
		System.out.println(fun.apply(new Employee()));
		
		System.out.println("-----------------------------------------");
		
		Function<Employee, String> fun2 = Employee::show;
		System.out.println(fun2.apply(new Employee()));
		
	}
	
	//類名 :: 靜態方法名
	@Test
	public void test4(){
		Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
		
		System.out.println("-------------------------------------");
		
		Comparator<Integer> com2 = Integer::compare;
	}
	
	@Test
	public void test3(){
		BiFunction<Double, Double, Double> fun = (x, y) -> Math.max(x, y);
		System.out.println(fun.apply(1.5, 22.2));
		
		System.out.println("--------------------------------------------------");
		
		BiFunction<Double, Double, Double> fun2 = Math::max;
		System.out.println(fun2.apply(1.2, 1.5));
	}

	//物件的引用 :: 例項方法名
	@Test
	public void test2(){
		Employee emp = new Employee(101, "張三", 18, 9999.99);
		
		Supplier<String> sup = () -> emp.getName();
		System.out.println(sup.get());
		
		System.out.println("----------------------------------");
		
		Supplier<String> sup2 = emp::getName;
		System.out.println(sup2.get());
	}
	
	@Test
	public void test1(){
		PrintStream ps = System.out;
		Consumer<String> con = (str) -> ps.println(str);
		con.accept("Hello World!");
		
		System.out.println("--------------------------------");
		
		Consumer<String> con2 = ps::println;
		con2.accept("Hello Java8!");
		
		Consumer<String> con3 = System.out::println;
	}
	
}

Stream

  • Stream 是 Java8 中處理集合的關鍵抽象概念,它可以指定你希望對集合進行的操作,可以執行非常複雜的查詢、過濾和對映資料等操作。
  • Stream是資料渠道,用於操作資料來源(集合、陣列等)所生成的元素序列。
  • 注意:
    1. Stream 自己不會儲存元素。
    2. Stream 不會改變源物件。相反,他們會返回一個持有結果的新Stream。
    3. Stream 操作是延遲執行的。這意味著他們會等到需要結果的時候才執行。
  • Stream 的操作三個步驟:
    1. 建立 Stream
    2. 中間操作
    3. 終止操作
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import org.junit.Test;

/*
 * 一、Stream API 的操作步驟:
 * 
 * 1. 建立 Stream
 * 
 * 2. 中間操作
 * 
 * 3. 終止操作(終端操作)
 */
public class TestStreamaAPI {
	
	//1. 建立 Stream
	@Test
	public void test1(){
		//1. Collection 提供了兩個方法  stream() 與 parallelStream()
		List<String> list = new ArrayList<>();
		Stream<String> stream = list.stream(); //獲取一個順序流
		Stream<String> parallelStream = list.parallelStream(); //獲取一個並行流
		
		//2. 通過 Arrays 中的 stream() 獲取一個數組流
		Integer[] nums = new Integer[10];
		//static <T> Stream<T> stream(T[] array)
		Stream<Integer> stream1 = Arrays.stream(nums);
		
		//3. 通過 Stream 類中靜態方法 of()
		//public static<T> Stream<T> of(T... values)
		Stream<Integer> stream2 = Stream.of(1,2,3,4,5,6);
		
		//4. 建立無限流
		//迭代
		//public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
		Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 2);
		
		//生成
		//public static<T> Stream<T> generate(Supplier<T> s)
		Stream<Double> stream4 = Stream.generate(Math::random);
	}
	
	//2. 中間操作
	//這裡假設我們建立了一個Employee類
	List<Employee> emps = Arrays.asList(
			new Employee(102, "李四", 59, 6666.66),
			new Employee(101, "張三", 18, 9999.99),
			new Employee(103, "王五", 28, 3333.33),
			new Employee(104, "趙六", 8, 7777.77),
			new Employee(104, "趙六", 8, 7777.77),
			new Employee(104, "趙六", 8, 7777.77),
			new Employee(105, "田七", 38, 5555.55)
	);
	
	/*
	  篩選與切片
		filter(Predicate p)——接收 Lambda , 從流中排除某些元素。
		limit(long maxSize)——截斷流,使其元素不超過給定數量。
		skip(long n) —— 跳過元素,返回一個扔掉了前 n 個元素的流。若流中元素不足 n 個,則返回一個空流。與 limit(n) 互補
		distinct()——篩選,通過流所生成元素的 hashCode() 和 equals() 去除重複元素
	 */
	
	//內部迭代:迭代操作 Stream API 內部完成
	@Test
	public void test2(){
		//所有的中間操作不會做任何的處理
		Stream<Employee> stream = emps.stream()
			.filter((e) -> {
				System.out.println("測試中間操作");
				return e.getAge() <= 35;
			});
		
		//只有當做終止操作時,所有的中間操作會一次性的全部執行,稱為“惰性求值”
		stream.forEach(System.out::println);
	}
	
	@Test
	public void test3(){
		emps.parallelStream()
			.filter((e) -> e.getSalary() >= 5000)
			.skip(2)
			.forEach(System.out::println);//屬於終止操作
	}
	
	@Test
	public void test4(){
		emps.stream()
			.distinct()
			.forEach(System.out:
            
           

相關推薦

Java學習筆記--Java8特性

Lambda表示式 Lambda表示式的作用就是在代替冗長的匿名內部類,使用簡潔的方式重寫介面中的抽象方法,並建立子類物件。 Lambda表示式被"->"操作符分成兩部分,左側表示引數列表,右側表示所執行的功能。 Lambda表示式需要函式式介面的支援

尚矽谷學習筆記——Java8特性

2014年3月釋出 公司往往不是追求技術的新,而且追求技術的穩定。所以大多用的之前的版本。 Java 8 新特性簡介 速度更快 修改底層資料結構:如HashMap(陣列-連結串列-紅黑樹),HashSet,ConcurrentHashMap(CAS演算

2018.10.15學習筆記——H5特性

.com 代碼 分享 筆記 bubuko 引入 解決 瀏覽器 動態創建 一、新標簽兼容ie678方式:   1.動態創建標簽;   2.引入別人寫好的兼容插件;   3.完美解決方式:cc:ie6;   上代碼:         二、video/audio標簽兼容方式:  

java學習筆記(十)-- java特性 (列舉 & 註解 & 介面定義加強 & Lambda表示式)

列舉 (enum) 高階的多例模式 java中列舉使用enum關鍵字定義列舉 列舉就是一種多例設計模式 enmu Color{     RED,BLUE,GREEN;     } enum Color{

java學習筆記(九)-- java特性 ( 可變引數 & 泛型 & 靜態匯入 & 型別擦除 )

JDK1.5新特性 方法的可變引數             設計一個方法,可以接收任意個數的整數,並返回他們的相加結果       

JAVA8特性學習筆記

一、Lamda表示式 在JAVA8新特性中主要一點就是支援了Lamda表示式,這為我們開發帶來了一些便利。 傳統中我們實現匿名內部類是這樣的: package cn.com; interface Message {// 這適宜個一個介面 public void print

Java精品高級課,架構課,java8特性,P2P金融項目,程序設計,功能設計,數據庫設計,第三方支付,web安全,視頻教程

數據庫設計 zfs 調優 pex 完整版 city 後臺 中間件 集群 36套精品Java架構師,高並發,高性能,高可用,分布式,集群,電商,緩存,性能調優,設計模式,項目實戰,P2P金融項目,大型分布式電商實戰視頻教程 視頻課程包含: 高級Java架構師包含:Sp

java8特性學習:stream與lambda

包含 term strong java statistic 管道 特定 getname java8新特性 Streams api 對 Stream 的使用就是實現一個 filter-map-reduce 過程,產生一個最終結果,或者導致一個副作用(side effect)

36套精品Java高級課,架構課,java8新特性,P2P金融項目,程序設計,功能設計,數據庫設計,第三方支付,web安全,高並發,高性能,高可用,分布式,集群,電商,緩存,性能調優,設計模式,項目實戰,大型分布式電商項目實戰視頻教程

java cti 投資 調優 dubbo pac 性能 -s clas 36套精品Java高級課,架構課,java8新特性,P2P金融項目,程序設計,功能設計,數據庫設計,第三方支付,web安全,高並發,高性能,高可用,分布式,集群,電商,緩存,性能調優,設計模式,項

Java學習筆記二十一:Java面向對象的三大特性之繼承

類構造 接下來 多重 通過 prot 圖片 等級 ++ class Java面向對象的三大特性之繼承 一:繼承的概念;   繼承是java面向對象編程技術的一塊基石,因為它允許創建分等級層次的類。   繼承就是子類繼承父類的特征和行為,使得子類對象(實例)具有父

Java架構師,微服務架構設計,並發編程,java8特性,P2P金融項目,高並發,分布式

環境 span acc 要掌握 system 精益 app 擴展 ant 微服務架構設計 微服務 軟件架構是一個包含各種組織的系統組織,這些組件包括 Web服務器, 應用服務器, 數據庫,存儲, 通訊層), 它們彼此或和環境存在關系。系統架構的目標是解決利益

Java8 特性筆記

public void test01() { Comparator<Integer> comparator1 = new Comparator<Integer>() { @Override public int

【小家javaJava8特性之---CompletableFuture的系統講解和例項演示(使用CompletableFuture構建非同步應用)

相關閱讀 【小家java】java5新特性(簡述十大新特性) 重要一躍 【小家java】java6新特性(簡述十大新特性) 雞肋升級 【小家java】java7新特性(簡述八大新特性) 不溫不火 【小家java】java8新特性(簡述十大新特性) 飽受讚譽 【小家java】java9

java8特性筆記

1、排序 List<String> names = Arrays.asList("peter", "anna", "mike", "xenia"); names.sort((a, b) -> a.compareTo(b)); 將names列表按首字母排序。 2、流式程式設計 j

Java8特性學習-總結

1. 介面的擴充套件方法 Java8允許給介面新增一個非抽象的方法,只需要使用default關鍵字即可,這個特徵又叫做擴充套件方法。 程式碼:定義Formula 介面,接口裡定義非抽象方法sqrt,並用default修飾 interface Formula { do

Java8特性之Lambda表示式學習

大家好,又來到超超部落格大本營啦!歡迎大家...... 上一章我們講解了Lambda表示式的基礎語法,引數列表、變數等知識點,接下來我們接續探究Lambda的表示式、以及其中的方法引用。 一、Lambda的表示式: (1)如果表示式只有一行,那麼可以直接寫(不需要{}); (2)

Java8特性之Lambda表示式學習

       剛畢業入職新工作,在職崗位培訓時,老師在操作集合老使用Lambda表示式。這使一個之前完全沒有接觸過Lambda表示式的少年甚是苦惱,看不懂,閒餘時間決定搞一搞Lambda表示式到底是啥東西?底層原理怎麼實現的,接下來我將我的學習成果一起分享

java8特性之lamda表示式應用java策略模式

java8的lamda表示式提供了有四種最常用的函式式介面型別:簡單理解函式式介面:就是介面中只有一個抽象方法的介面 1:消費型介面:Consumer  有入參 無返回介面 2:供給型介面:Supplier   無入參 有返回結果 3:function介面:

JAVA秒會技術之Java8特性】利用流快速處理集合的常見操作

例子1:對集合進行排序 List<Integer> list = Lists.newArrayList(1,1,2,2,5,3,4,6,6,5,2,7); list.sort(null); list.forEach(e -> System.out.prin

Java8學習筆記日期API

Java8對日期API做了改進,提供了許多好用的方法和介面。 首先,最基本也最重要的3個物件: - LocalDate:日期物件 - LocalTime:時間物件 - LocalDateTime:日期時間物件,是LocalDate和LocalTime