Java Stream中自定義Collector實(shí)現(xiàn)復(fù)雜數(shù)據(jù)收集的方法
1. Collector接口的作用
Collector接口定義了數(shù)據(jù)收集、轉(zhuǎn)換和聚合的基本操作,使得從Stream中收集到特定的數(shù)據(jù)結(jié)構(gòu)或執(zhí)行復(fù)雜的聚合操作成為可能。Collector接口為Stream操作提供了一個(gè)終止方法,將Stream的處理結(jié)果收集到一個(gè)特定的容器中。
2. Collector接口的組成
Collector接口包含以下五個(gè)主要方法:
supplier():返回一個(gè)新的結(jié)果容器的
Supplier。這個(gè)方法用于創(chuàng)建用于存儲(chǔ)收集結(jié)果的容器。accumulator():接收一個(gè)結(jié)果容器和一個(gè)流中的元素,將元素添加到結(jié)果容器中。這是累積元素的核心方法,用于將流中的元素逐個(gè)添加到結(jié)果容器中。
combiner():接收兩個(gè)結(jié)果容器,合并它們。在并行流處理中,如果有多個(gè)結(jié)果容器被生成,則使用
combiner()方法將它們合并為一個(gè)容器。finisher():接收一個(gè)結(jié)果容器,返回最終結(jié)果。這個(gè)方法通常用于將結(jié)果容器轉(zhuǎn)換為最終想要的形式,例如,對(duì)容器中的元素進(jìn)行排序或過(guò)濾。
characteristics():返回一個(gè)不可變的Set,包含收集器的特性。這些特性用于優(yōu)化流處理過(guò)程,如并行流處理或結(jié)果的無(wú)序性。
3. Collector接口的工作原理
Collector接口的工作原理基于上述五個(gè)方法的協(xié)作。先通過(guò)supplier()方法創(chuàng)建一個(gè)新的結(jié)果容器。然后,遍歷Stream中的每個(gè)元素,使用accumulator()方法將元素添加到結(jié)果容器中。在并行流處理中,如果有多個(gè)結(jié)果容器被生成,則使用combiner()方法將它們合并為一個(gè)容器。最后,通過(guò)finisher()方法將結(jié)果容器轉(zhuǎn)換為最終想要的形式,并返回。
4. Collector的預(yù)定義實(shí)現(xiàn)Collectors
Collectors可以看做是Collector接口的實(shí)現(xiàn)工廠(chǎng),提供了多個(gè)用于數(shù)據(jù)收集、轉(zhuǎn)換和聚合的預(yù)定義收集器,如toList()、toSet()、toMap()、joining()、counting()、summingInt()、averagingInt()等。這些收集器利用Collector接口實(shí)現(xiàn),使得從Stream中收集數(shù)據(jù)變得更為方便和高效。
List<String> list = Stream.of("a", "b", "c")
.collect(Collectors.toList());
Map<Character, List<String>> grouped = Stream.of("a", "b", "c")
.collect(Collectors.groupingBy(s -> s.charAt(0)));
String joined = Stream.of("a", "b", "c")
.collect(Collectors.joining(", "));
如,toList()收集器通過(guò)調(diào)用new ArrayList<>()來(lái)創(chuàng)建一個(gè)新的結(jié)果容器,并使用accumulator()方法將流中的元素添加到結(jié)果容器中。toMap()收集器則創(chuàng)建一個(gè)新的HashMap,并使用提供的鍵函數(shù)和值函數(shù)將元素映射到Map的鍵和值上。
5. 自定義Collector的使用場(chǎng)景
通過(guò)實(shí)現(xiàn)Collector接口來(lái)自定義復(fù)雜的收集器,以滿(mǎn)足特定的數(shù)據(jù)處理需求。自定義Collector時(shí),要實(shí)現(xiàn)上述五個(gè)方法,并定義如何收集、轉(zhuǎn)換和聚合數(shù)據(jù)。
如,自定義Collector對(duì)Person對(duì)象進(jìn)行排序,并根據(jù)特定條件進(jìn)行分組:
public static class CustomCollector<T> implements Collector<Person, List<Person>, Map<String, List<Person>>> {
@Override
public Supplier<List<Person>> supplier() {
return ArrayList::new;
}
@Override
public BiConsumer<List<Person>, Person> accumulator() {
return (list, person) -> list.add(person);
}
@Override
public BinaryOperator<List<Person>> combiner() {
return (list1, list2) -> {
list1.addAll(list2);
return list1;
};
}
@Override
public Function<List<Person>, Map<String, List<Person>>> finisher() {
return list -> {
Map<String, List<Person>> result = new HashMap<>();
// 自定義排序規(guī)則
list.sort((p1, p2) -> {
if (p1.age != null && p2.age != null) {
return p1.age.compareTo(p2.age);
} else if (p1.age != null) {
return -1;
} else if (p2.age != null) {
return 1;
} else {
return p1.name.compareTo(p2.name);
}
});
// 自定義分組規(guī)則
for (Person person : list) {
if (result.containsKey(person.name.substring(0, 2))) {
result.get(person.name.substring(0, 2)).add(person);
} else {
List<Person> group = new ArrayList<>();
group.add(person);
result.put(person.name.substring(0, 2), group);
}
}
return result;
};
}
@Override
public Set<Collector.Characteristics> characteristics() {
return EnumSet.of(Collector.Characteristics.IDENTITY_FINISH);
}
}
自定義收集、轉(zhuǎn)換和聚合Person對(duì)象的邏輯。使用自定義的排序和分組規(guī)則,根據(jù)姓名和年齡將Person對(duì)象分組并排序,最終返回Map<String, List<Person>>。
通過(guò)自定義Collector,創(chuàng)建特定的收集器,而滿(mǎn)足復(fù)雜的數(shù)據(jù)處理需求。
使用方法:
import java.util.*;
public class CustomCollectorDemo {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 25),
new Person("Bob", 23),
new Person("Charlie", 28),
new Person("David", 25),
new Person("Eva", 23),
new Person("Frank", 28)
);
Map<String, List<Person>> result = people.stream()
.collect(new CustomCollector<>());
System.out.println(result);
}
static class Person {
String name;
Integer age;
...
}
}
到此這篇關(guān)于Java Stream中自定義Collector實(shí)現(xiàn)復(fù)雜數(shù)據(jù)收集的方法的文章就介紹到這了,更多相關(guān)Java Stream自定義Collector數(shù)據(jù)收集內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java通過(guò)snmp協(xié)議獲取物理設(shè)備信息
這篇文章主要介紹了java通過(guò)snmp協(xié)議獲取物理設(shè)備信息,snmp中文含義是簡(jiǎn)單網(wǎng)絡(luò)管理協(xié)議,可用完成對(duì)計(jì)算機(jī)、路由器和其他網(wǎng)絡(luò)設(shè)備的遠(yuǎn)程管理和監(jiān)視,本文我們是通過(guò)java程序來(lái)獲取,需要的朋友可以參考下2023-07-07
Java開(kāi)發(fā)環(huán)境不再需要配置classpath問(wèn)題
這篇文章主要介紹了Java開(kāi)發(fā)環(huán)境不再需要配置classpath問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
Spring WebFlux使用函數(shù)式編程模型構(gòu)建異步非阻塞服務(wù)
這篇文章主要介紹了Spring WebFlux使用函數(shù)式編程模型構(gòu)建異步非阻塞服務(wù),重點(diǎn)介紹如何使用函數(shù)式編程模型創(chuàng)建響應(yīng)式 RESTful 服務(wù),這種編程模型與傳統(tǒng)的基于 Spring MVC 構(gòu)建 RESTful 服務(wù)的方法有較大差別,感興趣的朋友跟隨小編一起看看吧2023-08-08
SpringBoot使用Feign調(diào)用其他服務(wù)接口
這篇文章主要介紹了SpringBoot使用Feign調(diào)用其他服務(wù)接口,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
Java線(xiàn)程安全解決方案(synchronized,ReentrantLock,Atomic)
這篇文章主要介紹了Java線(xiàn)程安全解決方案(synchronized,ReentrantLock,Atomic),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
spring boot openfeign從此和httpClient說(shuō)再見(jiàn)詳析
這篇文章主要給大家介紹了關(guān)于spring boot openfeign從此和httpClient說(shuō)再見(jiàn)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧2018-06-06
Java實(shí)現(xiàn)度分秒坐標(biāo)轉(zhuǎn)十進(jìn)制度
隨著技術(shù)的發(fā)展,十進(jìn)制度因其精確性和便捷性在現(xiàn)代應(yīng)用中越來(lái)越受到青睞,下面我們就來(lái)看看如何使用Java實(shí)現(xiàn)度分秒坐標(biāo)轉(zhuǎn)十進(jìn)制度吧2024-12-12
SpringBoot中的錯(cuò)誤處理機(jī)制源碼解析
這篇文章主要介紹了SpringBoot中的錯(cuò)誤處理機(jī)制源碼解析,springboot根據(jù)訪(fǎng)問(wèn)者的request中的Accept屬性來(lái)判斷要返回什么樣的數(shù)據(jù),SpringBoot存在一個(gè)錯(cuò)誤處理機(jī)制,會(huì)根據(jù)不同請(qǐng)求返回不同的結(jié)果,需要的朋友可以參考下2023-12-12
@RequestBody和@RequestParam接受參數(shù)的情況分析
文章主要介紹了@RequestBody注解在Spring?MVC中的使用,包括其接收前端傳遞的JSON數(shù)據(jù)、與@RequestParam()的配合使用,以及JSON數(shù)據(jù)與后端對(duì)象屬性的匹配規(guī)則2026-03-03

