java8中Lambda表達式和Stream API
一、Lambda表達式
1.語法格式
Lambda是匿名函數,可以傳遞代碼。使用“->”操作符,改操作符將lambda分成兩部分:
左側:指定了 Lambda 表達式需要的所有參數
右側:指定了 Lambda 體,即 Lambda 表達式要執行的功能,也就是實現接口方法的代碼
// 語法格式一:無參、無返回值
@Test
public void test1() {
Runnable runable = () -> System.out.println("hello lambda!");
runable.run();
}
// 語法格式二:有一個參、無返回值
@Test
public void test2() {
Consumer<String> consumer = (args) -> System.out.println("hello!"
+ args);
consumer.accept("lambda");
}
// 語法格式三:有多個參、有返回值,并且有多條執行語句,用大括號包圍
@Test
public void test3() {
Comparator<Integer> com = (x, y) -> {
System.out.println("hello lambda!");
return Integer.compare(x, y);
};
int rs = com.compare(2, 2);
System.out.println(rs);
}
// 語法格式四:右側如果只有一條執行語句,可以省略大括號和return
@Test
public void test4() {
Comparator<Integer> com = (Integer x, Integer y) -> Integer.compare(x, y);
int rs = com.compare(2, 2);
System.out.println(rs);
}
注:lambd可以省略接口參數類型,java編譯器會根據上下文進行類型推斷
2.函數式接口
(1)只包含一個抽象方法的接口,稱為函數式接口,可以在任意函數式接口上使用 @FunctionalInterface 注解,lambda需要函數式接口的支持。
(2)java8內置四大核心函數式接口:
Consumer<T>消費型接口:void accept(T t)
@Test
public void test2() {
Consumer<String> consumer = (args) -> System.out.println("hello!"
+ args);
consumer.accept("lambda");
}
Supplier<T>供給型接口:T get()
@Test
public void test5() {
List<Integer> rs=getNumList(6,() -> (int)(Math.random()*100));
System.out.println(rs);
}
public List<Integer> getNumList(int size,Supplier<Integer> sup){
List<Integer> list=new ArrayList<Integer>();
for (int i = 0; i < size; i++) {
Integer e=sup.get();
list.add(e);
}
return list;
}
Function<T, R>函數型接口:R apply(T t)
@Test
public void test6() {
Function<String, Integer> fun=(str)->str.length();
int len=fun.apply("lambda");
System.out.println(len);
}
Predicate<T>斷定型接口:boolean test(T t)
@Test
public void test7() {
Predicate<String> check=(str)->str.equals("lambda");
boolean rs=check.test("lambda");
System.out.println(rs);
}
3.方法引用
當要傳遞給Lambda體的操作,已經有實現的方法了,可以使用方法引用!( lambda要實現抽象方法的參數列表,必須與方法引用的方法參數列表保持一致! )。
方法引用:使用操作符 “ ::” 將對象或類和方法的名字分隔開來。
三種主要使用情況:
對象::方法名
PrintStream ps=System.out;
Consumer<String> consumer = ps::println;
consumer.accept("lambda");
類::靜態方法名
Comparator<Integer> com = Integer::compare; int rs = com.compare(2, 2); System.out.println(rs);
類::實例方法名(前提條件:lambda參數列表的第一個參數是實例方法的調用者,第二個參數是實例方法的入參)
BiPredicate<String,String> check=(str1,str2)->str1.equals(str2); BiPredicate<String,String> check1=String::equals;
4.構造器引用
與函數式接口相結合,自動與函數式接口中方法兼容(需要調用的構造器方法參數列表要與函數式接口中方法的參數列表一致)
格式: ClassName::new
5.數組引用
格式: type[] :: new
二、Stream API
1.說明解釋
Stream 是 Java8 中處理集合的關鍵抽象概念,它可以指定你希望對集合進行的操作,可以執行非常復雜的查找、過濾和映射數據等操作。使用Stream API 對集合數據進行操作,就類似于使用 SQL 執行的數據庫查詢。也可以使用 Stream API 來并行執行操作。簡而言之,Stream API 提供了一種高效且易于使用的處理數據的方式。流(Stream)是數據渠道,用于操作數據源(集合、數組等)所生成的元素序列。“集合講的是數據,流講的是計算! ”
注意:
①Stream 自己不會存儲元素。
②Stream 不會改變源對象。相反,他們會返回一個持有結果的新Stream。
③Stream 操作是延遲執行的。這意味著他們會等到需要結果的時候才執行。
2.Stream 操作步驟
(1)創建Stream
①可以通過Collection系列集合提供的stream()或者parallelStream()獲得
List<String> list=new ArrayList<String>(); Stream<String> stream=list.stream();
②可以通過Arrays的靜態方法stream()獲得數組流
Person[] ps=new Person[10]; Stream<Person> stream=Arrays.stream(ps);
③可以通過Stream的靜態of()
Stream<String> steam=Stream.of("aa","bb","cc");
④可以使用靜態方法 Stream.iterate() 和Stream.generate(), 創建無限流
(2)中間條件操作
說明:多個中間操作可以連接起來形成一個流水線,除非流水線上觸發終止操作,否則中間操作不會執行任何的處理!而在終止操作時一次性全部處理,稱為“惰性求值”。
①篩選與切片
filter——接收 Lambda , 從流中排除某些元素。
limit——截斷流,使其元素不超過給定數量。
skip(n) —— 跳過元素,返回一個扔掉了前 n 個元素的流。若流中元素不足 n 個,則返回一個空流。與 limit(n) 互補
distinct——篩選去重,通過流所生成元素的 hashCode() 和 equals() 去除重復元素
List<Person> personList = Arrays.asList(
new Person("李四", 20, 10),
new Person("張三", 40,30),
new Person("王五", 28, 15),
new Person("趙六", 60, 60),
new Person("趙六", 60, 60),
new Person("趙六", 60, 60),
new Person("田七", 8,2)
);
Stream<Person> stream=personList.stream();
stream.filter((p)->p.getAge()>20)//過濾保留age>20
.limit(5)//只取前兩個
.skip(1)//跳過前一個,返回剩下的
.distinct()//去重,自動定義對象去重要重寫equals和hashcode
.forEach(System.out::println);
②映射
map——接收 Lambda,將元素轉換成其他形式或提取信息。接收一個函數作為參數,該函數會被應用到每個元素上,并將其映射成一個新的元素。
flatMap——接收一個函數作為參數,將流中的每個值都換成另一個流,然后把所有流連接成一個流
Stream<Person> stream=personList.stream(); stream.map((p)->p.getName())//提取name,組成新的Stream流 .forEach(System.out::println);
③排序
sorted()——自然排序(Comparable)
sorted(Comparator com)——定制排序
(3)執行操作
①查找與匹配
allMatch——檢查是否匹配所有元素,返回boolean
anyMatch——檢查是否至少匹配一個元素,返回boolean
noneMatch——檢查是否沒有匹配的元素,返回boolean
findFirst——返回第一個元素
findAny——返回當前流中的任意一個元素
count——返回流中元素的總個數
max——返回流中最大值
min——返回流中最小值
浙公網安備 33010602011771號