Java?8?Stream?處理數據方法匯總
Stream流
Stream流是什么,為什么要用它
- Stream是Java 8 新引入的一個包( java.util.stream),它讓我們能用聲明式的方式處理數據(集合、數組等)。
- Stream流式處理相較于傳統(tǒng)方法簡潔高效,也便于進行并發(fā)編程。
- Stream
Stream是Java8的一大亮點,是對容器對象功能的增強,它專注于對容器對象進行各種非常便利、高效的 聚合操作(aggregate operation)或者大批量數據操作。Stream 使用一種類似用 SQL 語句從數據庫查詢數據的直觀方式來提供一種對 Java 集合運算和表達的高階抽象。Stream API借助于同樣新出現的Lambda表達式,極大的提高編程效率和程序可讀性。同時,它提供串行和并行兩種模式進行匯聚操作,并發(fā)模式能夠充分利用多核處理器的優(yōu)勢,使用fork/join并行方式來拆分任務和加速處理過程。所以說,Java8中首次出現的 java.util.stream是一個函數式語言+多核時代綜合影響的產物。
Stream流的基礎使用
簡單綜合案例
問題和需求:在一個字符串集合中找出以“阿”開頭的長度為3的字符串并打印
傳統(tǒng)方法
import java.util.ArrayList;
import java.util.List;
public class Demo02NormalFilter {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("阿拉貢");
list.add("阿爾玟");
list.add("埃爾隆德");
list.add("凱蘭崔爾");
list.add("瑟蘭督伊");
List<String> zhangList = new ArrayList<>();
for (String name : list) {
if (name.startsWith("阿")) {
zhangList.add(name);
}
}
List<String> shortList = new ArrayList<>();
for (String name : zhangList) {
if (name.length() == 3) {
shortList.add(name);
}
}
for (String name : shortList) {
System.out.println(name);
}
}
}這里我們可以看到傳統(tǒng)的方法中含有三個循環(huán),每一個作用不同:
- 首先篩選所有姓“阿”的人;
- 然后篩選名字有三個字的人;
- 最后進行對結果進行打印輸出。
這樣的處理過程代碼冗長,導致代碼可讀性較差,效率也比較低。 而使用Stream來進行處理就能使代碼優(yōu)雅地多。
Stream流式處理方法
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class Demo02NormalFilter {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("阿拉貢");
list.add("阿爾玟");
list.add("埃爾隆德");
list.add("凱蘭崔爾");
list.add("瑟蘭督伊");
list.stream()
.filter(s ‐> s.startsWith("阿"))
.filter(s ‐> s.length() == 3)
.forEach(System.out::println);
}
}利用Stream流中的方法再結合函數式接口和Lambda表達式,我們的代碼就能變得格外簡潔明了。
獲取流
根據Collection獲取流
首先, java.util.Collection 接口中加入了default方法 stream 用來獲取流,所以其所有實現類均可獲取流。
import java.util.*;
import java.util.stream.Stream;
public class Demo04GetStream {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
Set<String> set = new HashSet<>();
Stream<String> stream2 = set.stream();
Vector<String> vector = new Vector<>();
Stream<String> stream3 = vector.stream();
}
}根據Map獲取流
java.util.Map 接口不是 Collection 的子接口,且其K-V數據結構不符合流元素的單一特征,所以獲取對應的流需要分key、value或entry等情況:
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
public class Demo05GetStream {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
//Stream流的轉化需要單列數據,那么我們就先把map里面的數據變成單列的再轉化為流
Stream<String> keyStream = map.keySet().stream();
Stream<String> valueStream = map.values().stream();
Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();
}
}根據數組獲取流
如果使用的不是集合或映射而是數組,由于數組對象不可能添加默認方法,所以 Stream 接口中提供了靜態(tài)方法of ,使用很簡單:
import java.util.stream.Stream;
public class Demo06GetStream {
public static void main(String[] args) {
String[] array = { "阿拉貢", "阿爾玟", "埃爾隆德", "凱蘭崔爾","瑟蘭督伊" };
Stream<String> stream = Stream.of(array);
}
}常用方法
流模型的操作很豐富,這里介紹一些常用的API。這些方法可以被分成兩種: 延遲方法:返回值類型仍然是 Stream 接口自身類型的方法,因此支持鏈式調用。(除了終結方法外,其余方法均為延遲方法。) 終結方法:返回值類型不再是 Stream 接口自身類型的方法,因此不再支持類似 StringBuilder 那樣的鏈式調用。接下來我會介紹兩個終結方法count 和 forEach 方法。
如果想知道更多方法,建議自行參考API文檔
逐一處理:forEach
雖然方法名字叫 forEach ,但是與for循環(huán)中的“for-each”語句是不一樣的 該方法接收一個 Consumer 接口函數,會將每一個流元素交給該函數進行處理。
方法簽名
void forEach(Consumer<? super T> action);
基本使用
import java.util.stream.Stream;
public class Demo12StreamForEach {
public static void main(String[] args) {
Stream<String> stream = Stream.of("阿拉貢", "阿爾玟", "埃爾隆德");
stream.forEach(name‐> System.out.println(name));
}
}篩選:filter
可以通過 filter 方法將一個流轉換成另一個子集流。 該方法接收一個 Predicate 函數式接口參數(可以是一個Lambda或方法引用)作為篩選條件。
方法簽名
Stream<T> filter(Predicate<? super T> predicate);
基本使用
import java.util.stream.Stream;
public class Demo07StreamFilter {
public static void main(String[] args) {
Stream<String> original = Stream.of("阿拉貢", "阿爾玟", "埃爾隆德");
Stream<String> result = original.filter(s ‐> s.startsWith("阿"));
}
}在這里通過Lambda表達式來指定了篩選的條件:必須以”阿“開頭。
映射:map
如果需要將流中的元素映射到另一個流中,可以使用 map 方法。 該接口需要一個 Function 函數式接口參數,可以將當前流中的T類型數據轉換為另一種R類型的流。
方法簽名
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
基本使用
import java.util.stream.Stream;
public class Demo08StreamMap {
public static void main(String[] args) {
Stream<String> original = Stream.of("10", "12", "18");
Stream<Integer> result = original.map(str‐>Integer.parseInt(str));
}
}這段代碼中, map 方法的參數通過方法引用,將字符串類型轉換成為了int類型(并自動裝箱為 Integer 類對象)。
統(tǒng)計個數:count
正如舊集合 Collection 當中的 size 方法一樣,流提供 count 方法來數一數其中的元素個數。 該方法返回一個long值代表元素個數(不再像舊集合那樣是int值)。
方法簽名
long count();
基本使用
import java.util.stream.Stream;
public class Demo09StreamCount {
public static void main(String[] args) {
Stream<String> original = Stream.of("阿拉貢", "阿爾玟", "埃爾隆德");
Stream<String> result = original.filter(s ‐> s.startsWith("阿"));
System.out.println(result.count()); // 2
}
}取用前幾個:limit
limit 方法可以對流進行截取,只取用前n個。 參數是一個long型,如果集合當前長度大于參數則進行截?。环駝t不進行操作。
方法簽名
Stream<T> limit(long maxSize);
基本使用
import java.util.stream.Stream;
public class Demo10StreamLimit {
public static void main(String[] args) {
Stream<String> original = Stream.of("阿拉貢", "阿爾玟", "埃爾隆德");
Stream<String> result = original.limit(2);
System.out.println(result.count()); // 2
}
}跳過前幾個:skip
如果希望跳過前幾個元素,可以使用 skip 方法獲取一個截取之后的新流。 如果流的當前長度大于n,則跳過前n個;否則將會得到一個長度為0的空流。
方法簽名
Stream<T> skip(long n);
基本使用
import java.util.stream.Stream;
public class Demo11StreamSkip {
public static void main(String[] args) {
Stream<String> original = Stream.of("阿拉貢", "阿爾玟", "埃爾隆德");
Stream<String> result = original.skip(2);
System.out.println(result.count()); // 1
}
}組合:concat
如果有兩個流,希望合并成為一個流,那么可以使用 Stream 接口的靜態(tài)方法 concat 。
這是一個靜態(tài)方法,與 java.lang.String 當中的 concat 方法是不同的。
方法簽名
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T>b)
基本使用
import java.util.stream.Stream;
public class Demo12StreamConcat {
public static void main(String[] args) {
Stream<String> streamA = Stream.of("阿拉貢");
Stream<String> streamB = Stream.of("阿爾玟");
Stream<String> result = Stream.concat(streamA, streamB);
}
}到此這篇關于Java 8 Stream 優(yōu)雅地處理數據的文章就介紹到這了,更多相關Java Stream 內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringMVC中使用@PathVariable綁定路由中的數組的方法
這篇文章主要介紹了SpringMVC中使用@PathVariable綁定路由中的數組的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-07-07

