Java如何實(shí)現(xiàn)一個(gè)簡(jiǎn)化版的Stream框架
Java 的 Stream API 中,延遲執(zhí)行(Lazy Evaluation)的核心在于中間操作不會(huì)立即執(zhí)行,而是在遇到終端操作時(shí),整個(gè)操作鏈才會(huì)執(zhí)行。這種機(jī)制通過(guò)將中間操作記錄為一系列的操作步驟,只有在需要結(jié)果時(shí),才將這些操作應(yīng)用于數(shù)據(jù)源。
可以通過(guò)記錄操作鏈的思想來(lái)模擬 Stream 的延遲執(zhí)行機(jī)制。簡(jiǎn)單來(lái)說(shuō),我們可以實(shí)現(xiàn)一個(gè)自定義的類來(lái)存儲(chǔ)這些操作,并在遇到終端操作時(shí)一次性執(zhí)行。
下面是一個(gè)簡(jiǎn)化版的 Stream 實(shí)現(xiàn),展示了如何通過(guò)延遲執(zhí)行來(lái)處理數(shù)據(jù)流。
簡(jiǎn)單實(shí)現(xiàn)的延遲執(zhí)行 Stream 類
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
public class SimpleStream<T> {
private final List<T> source; // 原始數(shù)據(jù)
private final List<Function<List<T>, List<T>>> operations = new ArrayList<>(); // 用于存儲(chǔ)操作鏈
public SimpleStream(List<T> source) {
this.source = source;
}
// 中間操作:filter
public SimpleStream<T> filter(Predicate<T> predicate) {
operations.add(list -> {
List<T> result = new ArrayList<>();
for (T item : list) {
if (predicate.test(item)) {
result.add(item);
}
}
return result;
});
return this;
}
// 中間操作:map
public <R> SimpleStream<R> map(Function<T, R> mapper) {
// 通過(guò) Function 將當(dāng)前 SimpleStream 轉(zhuǎn)換為新類型的 SimpleStream
SimpleStream<R> newStream = new SimpleStream<>(null);
operations.add(list -> {
List<R> result = new ArrayList<>();
for (T item : list) {
result.add(mapper.apply(item));
}
return result;
});
newStream.operations.addAll(this.operations); // 繼承父級(jí)操作鏈
return newStream;
}
// 終端操作:forEach,觸發(fā)延遲執(zhí)行
public void forEach(java.util.function.Consumer<T> consumer) {
List<T> result = applyOperations(source); // 在終端操作時(shí)應(yīng)用所有中間操作
for (T item : result) {
consumer.accept(item);
}
}
// 終端操作:collect
public List<T> collect() {
return applyOperations(source); // 在終端操作時(shí)應(yīng)用所有中間操作
}
// 應(yīng)用所有操作
private List<T> applyOperations(List<T> input) {
List<T> result = input;
for (Function<List<T>, List<T>> operation : operations) {
result = operation.apply(result); // 按順序應(yīng)用所有的操作
}
return result;
}
// 工廠方法:創(chuàng)建 SimpleStream
public static <T> SimpleStream<T> of(List<T> source) {
return new SimpleStream<>(source);
}
public static void main(String[] args) {
// 示例使用
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
SimpleStream.of(numbers)
.filter(x -> x > 2) // 延遲執(zhí)行的過(guò)濾操作
.map(x -> x * 2) // 延遲執(zhí)行的映射操作
.forEach(System.out::println); // 終端操作觸發(fā)執(zhí)行
}
}
代碼說(shuō)明
- 源數(shù)據(jù):
source存儲(chǔ)原始的數(shù)據(jù)列表,延遲執(zhí)行的所有操作都基于該列表。 - 操作鏈:
operations是一個(gè)List<Function<List<T>, List<T>>>,用于存儲(chǔ)中間操作。每個(gè)中間操作被表示為一個(gè)函數(shù),該函數(shù)接收并返回一個(gè)列表。 - 中間操作(filter 和 map):這些操作不會(huì)立即執(zhí)行,而是將對(duì)應(yīng)的操作邏輯以函數(shù)形式存儲(chǔ)在
operations中。filter和map分別通過(guò)謂詞和映射函數(shù)操作數(shù)據(jù)。 - 終端操作(forEach 和 collect):終端操作會(huì)觸發(fā)數(shù)據(jù)流的執(zhí)行,在這時(shí),所有的中間操作被按順序應(yīng)用到原始數(shù)據(jù)上。
applyOperations()方法負(fù)責(zé)遍歷operations,依次執(zhí)行操作鏈上的每一個(gè)操作。 - 示例:在
main()方法中,鏈?zhǔn)秸{(diào)用filter和map操作,最后通過(guò)forEach觸發(fā)計(jì)算并打印出結(jié)果。
運(yùn)行結(jié)果
6
8
10
總結(jié)
- 延遲執(zhí)行的核心思想是將中間操作的邏輯存儲(chǔ)起來(lái),而不立即對(duì)數(shù)據(jù)進(jìn)行處理。只有在終端操作(如
forEach、collect)被調(diào)用時(shí),才會(huì)真正執(zhí)行操作鏈中的所有步驟。 - 在這個(gè)簡(jiǎn)單的實(shí)現(xiàn)中,每個(gè)中間操作都存儲(chǔ)為一個(gè)函數(shù)(
Function<List<T>, List<T>>),在終端操作時(shí)依次應(yīng)用這些函數(shù)。
這個(gè)實(shí)現(xiàn)展示了如何通過(guò)存儲(chǔ)操作鏈并延遲執(zhí)行來(lái)實(shí)現(xiàn)類似 Stream 的處理方式。
到此這篇關(guān)于Java如何實(shí)現(xiàn)一個(gè)簡(jiǎn)化版的Stream框架的文章就介紹到這了,更多相關(guān)Java簡(jiǎn)化Stream框架內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java注解之超越Javadoc的元數(shù)據(jù)利器詳解
本文將深入探討 Java 注解的定義、類型、內(nèi)置注解、自定義注解、保留策略、實(shí)際應(yīng)用場(chǎng)景及最佳實(shí)踐,無(wú)論是初學(xué)者還是資深開(kāi)發(fā)者,都能通過(guò)本文了解如何利用注解提升代碼質(zhì)量和開(kāi)發(fā)效率2025-05-05
SpringCloud?中防止繞過(guò)網(wǎng)關(guān)請(qǐng)求直接訪問(wèn)后端服務(wù)的解決方法
這篇文章主要介紹了SpringCloud中如何防止繞過(guò)網(wǎng)關(guān)請(qǐng)求直接訪問(wèn)后端服務(wù),本文給大家分享三種解決方案,需要的朋友可以參考下2023-06-06
Java程序執(zhí)行時(shí)間的2種簡(jiǎn)單方法
這篇文章介紹了Java程序執(zhí)行時(shí)間的2種簡(jiǎn)單方法,有需要的朋友可以參考一下2013-09-09
詳解Mybatis是如何把數(shù)據(jù)庫(kù)數(shù)據(jù)封裝到對(duì)象中的
這篇文章主要介紹了Mybatis是如何把數(shù)據(jù)庫(kù)數(shù)據(jù)封裝到對(duì)象中的,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
Retrofit+RxJava實(shí)現(xiàn)帶進(jìn)度條的文件下載
這篇文章主要為大家詳細(xì)介紹了Retrofit+RxJava實(shí)現(xiàn)帶進(jìn)度條的文件下載,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-06-06
詳解RocketMQ 消費(fèi)端如何監(jiān)聽(tīng)消息
這篇文章主要為大家介紹了RocketMQ 消費(fèi)端如何監(jiān)聽(tīng)消息示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
MyBatis-Plus中的LambdaQuery用法實(shí)例詳解
LambdaQueryWrapper是MyBatis-Plus的類型安全查詢工具,通過(guò)Lambda表達(dá)式簡(jiǎn)化條件構(gòu)建,避免硬編碼字段名,提升代碼可讀性、維護(hù)性及重構(gòu)友好性,適用于單表查詢場(chǎng)景,本文給大家介紹MyBatis-Plus中的LambdaQuery用法,感興趣的朋友一起看看吧2025-07-07
解決IDEA和CMD中java命令提示錯(cuò)誤: 找不到或無(wú)法加載主類的問(wèn)題
這篇文章主要介紹了解決IDEA和CMD中java命令提示錯(cuò)誤: 找不到或無(wú)法加載主類的問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09

