Java8中有兩個非常有名的改進,一個是Lambda表達式,一個是Stream。如果我們瞭解過函數式編程的話,都知道Stream真正把函數式編程的風格引入到了java中。這篇文章由簡入繁逐步介紹Stream。
一、Stream是什麼
從名字來看,Stream就是一個流,他的主要作用就是對集合數據進行查找過濾等操作。有點類似於SQL的數據庫操作。一句話來解釋就是一種高效且易用的數據處理方式。大數據領域也有一個Steam實時流計算框架,不過和這個可不一樣。別搞混了。
舉個例子吧,比如說有一個集合Student數據,我們要刪選出學生名字爲“張三”的學生,或者是找出所有年齡大於18歲的所有學生。此時我們就可以直接使用Stream來篩選。當然了這只是給出了其中一個例子。Stream還有很多其他的功能。
Stream和Collection的區別就是:Collection只是負責存儲數據,不對數據做其他處理,主要是和內存打交道。但是Stream主要是負責計算數據的,主要是和CPU打交道。現在明白了吧。
二、Stream語法講解
Stream執行流程很簡單,主要有三個,首先創建一個Stream,然後使用Stream操作數據,最後終止Stream。有點類似於Stream的生命週期。下面我們根據其流程來一個一個講解。
1、前提準備
首先我們創建一個Student類,以後我們每次都是操作這個類
public class StreamTest {
public static List<Student> studentList;
static {
studentList = new ArrayList<>();
studentList.add(new Student(1, "劉備", 18, 90.4));
studentList.add(new Student(2, "張飛", 19, 87.4));
studentList.add(new Student(3, "關羽", 21, 67.4));
studentList.add(new Student(4, "趙雲", 15, 89.4));
studentList.add(new Student(5, "馬超", 16, 91.4));
studentList.add(new Student(6, "曹操", 19, 100.0));
studentList.add(new Student(7, "徐晃", 24, 78.4));
studentList.add(new Student(8, "孫權", 26, 79.4));
studentList.add(new Student(9, "魯肅", 21, 93.4));
}
public static void main(String[] args) {
}
}
2、使用Stream操作數據
操作1:篩選和切片
public static void filter() {
// 1、過濾所有年齡大於二十的同學
studentList.stream().filter(p -> p.getAge() > 20).forEach(System.out::println);
// 2、前三條數據
studentList.stream().limit(3).forEach(System.out::println);
// 3、跳過前五條數據
studentList.stream().skip(5).forEach(System.out::println);
// 4、過濾重複數據
studentList.stream().distinct().forEach(System.out::println);
}
操作2:映射
public static void test2() {
List<String> list = Arrays.asList("java", "python", "go");
Stream<String> stream = list.stream();
//此時每一個小寫字母都有一個大寫的映射
stream.map(String::toUpperCase).forEach(System.out::println);
// 篩選出所有年齡 在過濾大於20的年齡
List<Integer> collect = studentList.stream().map(Student::getAge).filter(p -> p > 20).collect(Collectors.toList());
System.out.println(collect);
}
操作3:排序
public static void test3() {
List<Integer> integers = Arrays.asList(4, 2, 5, 7, 23, 14, 15);
// 自然排序
// integers.stream().sorted().forEach(System.out::println);
// 對象排序
studentList.stream().sorted(Comparator.comparingInt(Student::getAge)).forEach(System.out::println);
}
操作4:匹配與查找
public static void test4() {
// 判斷所有學生的年齡是否都大於20
boolean allMatch = studentList.stream().allMatch(t -> t.getAge() > 20);
System.out.println("所有學生的年齡是否都大於20?" + allMatch);
// 判斷是否存在學生的年齡大於20的
boolean anyMatch = studentList.stream().anyMatch(t -> t.getAge() > 20);
System.out.println("判斷是否存在學生的年齡大於20的?" + anyMatch);
// 判斷是否存在一個學生名字叫曹操的
boolean noneMatch = studentList.stream().noneMatch(t -> t.getName().equals("曹操"));
System.out.println("判斷是否存在一個學生名字叫曹操的?" + noneMatch);
// 查找第一個學生
Optional<Student> first = studentList.stream().findFirst();
first.ifPresent(student -> System.out.println("查找第一個學生?" + student));
// 查詢所有學生的數量 使用studentList.size()更簡單
long count = studentList.stream().count();
System.out.println("查詢所有學生的數量" + count);
// 查詢最大成績
Optional<Double> max = studentList.stream().map(Student::getScore).max(Double::compareTo);
System.out.println(max);
}
操作5:歸納
public static void test5() {
// 計算總和
Optional<Double> reduce = studentList.stream().map(Student::getScore).reduce(Double::sum);
reduce.ifPresent(t -> System.out.println("所有學生成績總和" + t));
}
操作6:收集
public static void test6() {
// 轉換爲list
List<Student> collect = studentList.stream().filter(t -> t.getAge() > 20).collect(Collectors.toList());
System.out.println(collect);
// 轉化爲Set
Set<Student> studentSet = studentList.stream().filter(t -> t.getAge() > 20).collect(Collectors.toSet());
System.out.println(studentSet);
}
stream基本的語法就是這樣,你會發現Stream就像是一個工具一樣,可以幫我們分析處理數據,極其的好用,但是目前還不知道其效率如何。根據網上一位大佬的內存時間分析,其實在數據量比較龐大的時候,Stream可以爲我們節省大量的時間,數據量小的時候並不明顯。