1. 程式人生 > 實用技巧 >JDK 8 Stream 流 用 法

JDK 8 Stream 流 用 法

import com.entity.Person;
import org.junit.Test;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* @program: Demohander
* @description:JDK8新特性
* @author: GuoTong
* @create: 2020-11-18 10:14
**/
@SuppressWarnings("all")//正壓一切警告
public class JDKStreamTest {

/*Jdk1.8中引入了stream流的概念,
這個並不同於IO中的輸入和輸出流,
它是Jdk中的一個類,
具體位置在:java.util.stream.Stream*/


/*關於它的操作主要分為三種:獲取流、中間操作、最終操作*/

/*所謂獲取流,就是將其他物件(非Stream物件)轉為Stream物件。
只有兩類物件可能轉化為Stream物件,分別是:
陣列(這個陣列中的元素必須是引用型別)
集合*/

@Test
public void TestCreateStream() {
//陣列獲取流
Integer[] iArr = {12, 14, 15, 15, 17, 19, 22};
Stream<Integer> streamByArrInt = Stream.of(iArr);
// 陣列
String[] str = "I Love You But I miss You so I miss you".split(" ");
Stream<String> streamByArrStr = Arrays.stream(str);
//集合獲取流
List<String> list = Arrays.asList(str);
Stream<String> streamList = list.stream();

}

/*Stream流常用的中間操作:filter 過濾某些規則下的東西
* Stream流常用的終止操作:collect(Collectors.toList())---返回一個集合
* flatMap 可用Stream替換值,然後將多個Stream連線成一個Stream,會將之前生成Stream流的每一個元素更換為一個新的Stream物件。*/
@Test
public void TestStream01() {
//filter :
// filter方法用於通過設定的條件過濾出元素,下面的例子是過濾出長度大於3的字串
String[] s = "I Love You But I miss You so I miss you".split(" ");
List<String> list = Arrays.asList(s);
// List流轉:賽選大於3個欄位的,返回一個集合
/*list.stream().filter(str -> str.length() > 3):只是流操作了,原資料並未改變*/
/*list.stream().filter(str -> str.length() > 3).collect(Collectors.toList());返回的新集合就改變了*/
List<String> collect = list.stream().filter(str -> str.length() > 3).collect(Collectors.toList());
collect.forEach(System.out::println);//還是經過流處理的集合

//map
//map元素用於對映每隔元素到對應的結果,下面的例子用map輸出元素對應的平方數
Stream.of(1, 2, 3, 4, 5).map(i -> i * i).forEach(System.out::println);
System.out.println("============");
//flatMap 可用Stream替換值,然後將多個Stream連線成一個Stream,會將之前生成Stream流的每一個元素更換為一個新的Stream物件。
Stream<Integer> stream2 = Stream.of(1, 2).distinct()
.flatMap(numbers -> Stream.of(5, 6, 6, 7, 8));
//會將1,2都會替換為5,6,7,8,5,6,7,8
Object[] objects = stream2.toArray();
for (Object object : objects) {
System.out.println(object);
}
}

/*mapsorted測試*/
@Test
public void TestStream02() {
String[] str = {"1", "-12", "10", "23", "4", "7", "3"};
//map
//map元素內部遍歷集合,可以對集合元素一系列操作。
List<String> list = Arrays.asList(str);
/*將集合元素轉為大寫(每個元素對映到大寫)->降序排序->迭代輸出*/
/*原始字串的轉大寫,比較大小降序*/
Stream.of("a", "c", "f", "b", "w", "h", "z").map(String::toUpperCase).sorted((a, b) -> a.compareTo(b)).forEach(System.out::println);
System.out.println("====================================");
/*new Function<String, Integer>():標識型別轉換:第一個正規化需要轉換為第二個正規化的型別*/
list.stream().map(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return Integer.parseInt(s);
}
}).sorted((x, y) -> y - x).forEach(x -> System.out.print(x + ","));/*sorted((x,y)-> y-x):內部是compareTo方法實現,採用lambda表示式*/
/*x-> System.out.print(x+",") 對比 System.out::println ,前者可以自定義輸出內容,lambda表示式,後者只能原樣輸出*/
System.out.println("=================================");
list.stream().map(x -> x + "1").forEach(x -> System.out.print(x + ","));

}

/*mapsorted等較完整的鏈式程式設計*/
@Test
public void TestStream03() {
String[] str = {"17", "-12", "10", "23", "24", "17", "23", "15", "52", "12", "24", "14"};
List<String> list = Arrays.asList(str);
System.out.println("================集中多路=================");
/*集中多路鏈式程式設計*/
List<Integer> collect = list.stream().map(new Function<String, Integer>() {//型別轉化為int
@Override
public Integer apply(String s) {
return Integer.parseInt(s);
}
}).limit(5) //限制,只取前幾個元素
.skip(1) //跳過,表示跳過前幾個元素
.distinct() //去重
.sorted() //自然排序
.sorted(Integer::compareTo)//自定義排序,預設降序
.collect(Collectors.toList());//返回出去
collect.forEach(System.out::println);//列印
}

/*終止操作*/
@Test
public void TestStream04() {
//reduce:一般用於求和,第一個引數一般是結果的初始值,第二個引數操作
//靜態流:Stream.of(1,2,3)
Integer reduce = Stream.of(1, 2, 3, 4, 3, 2, 5, 1, 4, 2, 5).distinct().reduce(0, (x1, x2) -> x1 + x2);
System.out.println("不重的和:" + reduce);
//第二個:collect(Collectors.toList());將流轉化為XXXlistsethashset。。。。)
//stream.collect(Collectors.toCollection(HashSet::new));
String[] str = {"17", "-12", "10", "23", "24", "17", "23", "15", "52", "12", "24", "14"};
List<String> list = Arrays.asList(str);
HashSet<String> collect = list.stream().distinct().collect(Collectors.toCollection(HashSet::new));
Iterator<String> iterator = collect.iterator();//使用集合的迭代器迭代
while (iterator.hasNext()) {
String next = iterator.next();//迭代每一個元素
System.out.println(next);
}
//count方法是用來統計流中元素的個數
long count = Stream.of(1, 2, 3, 4, 3, 2, 5, 1, 4, 2, 5).distinct().count();
System.out.println("不重個數" + count);
}

/*Stream 流判空過濾*/
@Test
public void TestStream05() {
ArrayList<Person> arrayList = new ArrayList<>();
arrayList.add(new Person());
arrayList.add(null);
arrayList.add(new Person("小郭", 23));
arrayList.add(new Person("小李", 21));
arrayList.add(new Person("三少", 18));

/*過濾找出null*/
arrayList.stream().filter(Objects::isNull).forEach(person -> {
System.out.println("是空的");
});
System.out.println("=============================");
/*過濾找出不是null的,但是包含空參構造物件*/
arrayList.stream().filter(Objects::nonNull).forEach(person -> {
System.out.println(person.getAge());
System.out.println(person.getName());
});
/*arrayListnull的時候不會報空指標錯誤,並且還打了日誌。*/
System.out.println("=============================");
arrayList = null;
Optional.ofNullable(arrayList).orElseGet(() -> {
System.out.println("personList 是空的");
return new ArrayList<>();
}).stream().filter(Objects::nonNull).forEach(person -> {
System.out.println(person.getAge());
System.out.println(person.getName());
});
}

/*Stream的匹配操作:anymatch(是否涵蓋)
||allMatch(全部的原始是否都涵蓋)*/
@Test
public void TestStream06() {
//資料封裝
ArrayList<Person> arrayList = new ArrayList<>(); arrayList.add(
new Person()); arrayList.add(
null); arrayList.add(
new Person("小郭", 23)); arrayList.add(
new Person("小李", 21)); arrayList.add(

new Person("三少", 18));
//測試涵蓋
boolean anyMatch = Optional.ofNullable(arrayList).orElseGet(() -> { System.
out.println("personList 是空的");
return new ArrayList<>(); }).stream(). filter(Objects::

nonNull). filter(s -> s.getName() !=

null). anyMatch((person) -> person.getName().startsWith(
"")); String name = anyMatch ?
"涵蓋--->名字以字母開頭" : "不涵蓋"; System.
out.println(name); System.
out.println("=====================================");
//測試是否都滿足
boolean allMatch = Optional.ofNullable(arrayList).orElseGet(() -> { System.
out.println("personList 是空的");
return new ArrayList<>(); }).stream(). filter(Objects::

nonNull). filter(s -> s.getName() !=
null). allMatch(person -> person.getName().startsWith(
"")); String allName = allMatch ?
"全都--->名字以字母開頭" : "不全"; System.
out.println(allName); System.
out.println("=====================================");
/*noneMatch((s) -> s.startsWith("d"));集合中是否沒有元素匹配以'd'開頭*/
}

/*並行 parallelStream */
@Test
public void TestStreamToDouble() {
/*回去並行流的兩種方式*/
// 直接獲取並行的流
ArrayList<Integer> list = new ArrayList<>(); Stream<Integer> stream01 = list.parallelStream();

// 將序列流轉成並行流
ArrayList<Integer> list2 = new ArrayList<>(); Stream<Integer> stream02 = list2.stream().parallel();



/*大量資料時,並行流會比序列流更快:底層是Fork/Join框架;少量資料時,由於使用框架會損耗資源,所以建議用序列流*/
/*並行流和序列流比較*/
//順序輸出 123456789
List<Integer> numbers = Arrays.asList( 5, 6, 7, 8, 9,1, 2, 3, 4); numbers.stream().sorted().forEach(System.
out::print); System.

out.println();//換行

//並行亂序輸出 比如 658974132 此輸出不固定
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 3, 7, 2, 5);
//雖然寫了排序,但是輸出是未排序的;當然序列流不會,寫了排序就會排序
nums.parallelStream().distinct().sorted((x, y) -> x - y).forEach(x->System.out.println(x+",")); System.
out.println("===================");
// count()||collect()||reduce() 是終止操作,有終止操作才會執行中間操作sorted()
List<Integer> collect = nums.parallelStream().distinct().sorted((x, y) -> x - y).collect(Collectors.toList()); collect.forEach(System.
out::println);
/*部分情況會有執行緒安全問題,parallelStream裡面使用的外部變數,比如集合一定要使用執行緒安全集合,不然就會引發多執行緒安全問題*/
//建議使用JUC下的東西

}}