springboot升級到j(luò)dk21最新教程(2023年)
前言
隨著微服務(wù)的發(fā)展,越來越多的sql處理被放到j(luò)ava來處理,數(shù)據(jù)庫經(jīng)常會使用到對集合中的數(shù)據(jù)進(jìn)行分組求和,分組運(yùn)算等等。
那怎么樣使用java的stream優(yōu)雅的進(jìn)行分組求和或運(yùn)算呢?
一、準(zhǔn)備測試數(shù)據(jù)
這里測試數(shù)據(jù)學(xué)生,年齡類型是Integer,身高類型是BigDecimal,我們分別對身高個年齡進(jìn)行求和。
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
/**
* 姓名
*/
private String name;
/**
* 年齡
*/
private Integer age;
/**
* 身高
*/
private BigDecimal stature;
}
public class LambdaLearn {
// 初始化的測試數(shù)據(jù)集合
static List<Student> list = new ArrayList<>();
static {
// 初始化測試數(shù)據(jù)
list.add(new Student("張三", 18, new BigDecimal("185")));
list.add(new Student("張三", 19, new BigDecimal("185")));
list.add(new Student("張三2", 20, new BigDecimal("180")));
list.add(new Student("張三3", 20, new BigDecimal("170")));
list.add(new Student("張三3", 21, new BigDecimal("172")));
}
}
二、按學(xué)生姓名分組求年齡和(Integer類型的求和簡單示例)
1.實(shí)現(xiàn)
// 按學(xué)生姓名分組求年齡和
public static void main(String[] args) {
Map<String, Integer> ageGroup = list.stream().collect(Collectors.groupingBy(Student::getName
, Collectors.summingInt(Student::getAge)));
System.out.println(ageGroup);
}
執(zhí)行結(jié)果:
{張三=37, 張三3=41, 張三2=20}
三、按學(xué)生姓名分組求身高和(Collectors沒有封裝對應(yīng)的API)
1.實(shí)現(xiàn)一(推薦寫法)
思路:先分組,再map轉(zhuǎn)換成身高BigDecimal,再用reduce進(jìn)行求和
public static void main(String[] args) {
Map<String, BigDecimal> ageGroup = list.stream().collect(Collectors.groupingBy(Student::getName
, Collectors.mapping(Student::getStature, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
System.out.println(ageGroup);
}
執(zhí)行結(jié)果:
{張三=370, 張三3=342, 張三2=180}
2.實(shí)現(xiàn)二
思路:先分組,再收集成list,然后再map,再求和
public static void main(String[] args) {
Map<String, BigDecimal> ageGroup = list.stream().collect(Collectors.groupingBy(Student::getName
, Collectors.collectingAndThen(Collectors.toList()
, x -> x.stream().map(Student::getStature).reduce(BigDecimal.ZERO, BigDecimal::add))));
System.out.println(ageGroup);
}
執(zhí)行結(jié)果:
{張三=370, 張三3=342, 張三2=180}
3.實(shí)現(xiàn)三
思路:業(yè)務(wù)時常在分組后需要做一些判斷邏輯再進(jìn)行累加業(yè)務(wù)計(jì)算,所以自己實(shí)現(xiàn)一個收集器
1.封裝一個自定義收集器
public class MyCollector {
static final Set<Collector.Characteristics> CH_CONCURRENT_ID
= Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT,
Collector.Characteristics.UNORDERED,
Collector.Characteristics.IDENTITY_FINISH));
static final Set<Collector.Characteristics> CH_CONCURRENT_NOID
= Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT,
Collector.Characteristics.UNORDERED));
static final Set<Collector.Characteristics> CH_ID
= Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
static final Set<Collector.Characteristics> CH_UNORDERED_ID
= Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED,
Collector.Characteristics.IDENTITY_FINISH));
static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet();
private MyCollector() {
}
@SuppressWarnings("unchecked")
private static <I, R> Function<I, R> castingIdentity() {
return i -> (R) i;
}
/**
* @param <T> 集合元素類型
* @param <A> 中間結(jié)果容器
* @param <R> 最終結(jié)果類型
*/
static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
private final Supplier<A> supplier;
private final BiConsumer<A, T> accumulator;
private final BinaryOperator<A> combiner;
private final Function<A, R> finisher;
private final Set<Characteristics> characteristics;
CollectorImpl(Supplier<A> supplier,
BiConsumer<A, T> accumulator,
BinaryOperator<A> combiner,
Function<A, R> finisher,
Set<Characteristics> characteristics) {
this.supplier = supplier;
this.accumulator = accumulator;
this.combiner = combiner;
this.finisher = finisher;
this.characteristics = characteristics;
}
CollectorImpl(Supplier<A> supplier, // 產(chǎn)生結(jié)果容器
BiConsumer<A, T> accumulator, // 累加器
BinaryOperator<A> combiner, // 將多個容器結(jié)果合并成一個
Set<Characteristics> characteristics) {
this(supplier, accumulator, combiner, castingIdentity(), characteristics);
}
@Override
public BiConsumer<A, T> accumulator() {
return accumulator;
}
@Override
public Supplier<A> supplier() {
return supplier;
}
@Override
public BinaryOperator<A> combiner() {
return combiner;
}
@Override
public Function<A, R> finisher() {
return finisher;
}
@Override
public Set<Characteristics> characteristics() {
return characteristics;
}
}
public static <T> Collector<T, ?, BigDecimal> summingDecimal(ToDecimalFunction<? super T> mapper) {
return new MyCollector.CollectorImpl<>(
() -> new BigDecimal[1],
(a, t) -> {
if (a[0] == null) {
a[0] = BigDecimal.ZERO;
}
a[0] = a[0].add(Optional.ofNullable(mapper.applyAsDecimal(t)).orElse(BigDecimal.ZERO));
},
(a, b) -> {
a[0] = a[0].add(Optional.ofNullable(b[0]).orElse(BigDecimal.ZERO));
return a;
},
a -> a[0], CH_NOID);
}
}2.封裝一個函數(shù)式接口
@FunctionalInterface
public interface ToDecimalFunction<T> {
BigDecimal applyAsDecimal(T value);
}3.使用
public static void main(String[] args) {
Map<String, BigDecimal> ageGroup = list.stream().collect(Collectors.groupingBy(Student::getName
, MyCollector.summingDecimal(Student::getStature)));
System.out.println(ageGroup);
}
總結(jié)
自定義實(shí)現(xiàn)收集器可以參考Collectors的內(nèi)部類CollectorImpl的源碼,具體解析寫到注釋中。
推薦通過模仿Collectors.summingInt()的實(shí)現(xiàn)來實(shí)現(xiàn)我們自己的收集器。
// T代表流中元素的類型,A是中間處理臨時保存類型,R代表返回結(jié)果的類型
static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
private final Supplier<A> supplier;
private final BiConsumer<A, T> accumulator;
private final BinaryOperator<A> combiner;
private final Function<A, R> finisher;
private final Set<Characteristics> characteristics;
CollectorImpl(Supplier<A> supplier,
BiConsumer<A, T> accumulator,
BinaryOperator<A> combiner,
Function<A,R> finisher,
Set<Characteristics> characteristics) {
this.supplier = supplier;
this.accumulator = accumulator;
this.combiner = combiner;
this.finisher = finisher;
this.characteristics = characteristics;
}
CollectorImpl(Supplier<A> supplier,
BiConsumer<A, T> accumulator,
BinaryOperator<A> combiner,
Set<Characteristics> characteristics) {
this(supplier, accumulator, combiner, castingIdentity(), characteristics);
}
// 這里提供一個初始化的容器,用于存儲每次累加。即使我們求和這里也只能使用容器存儲,否則后續(xù)計(jì)算累加結(jié)果會丟失(累加結(jié)果不是通過返回值方式修改的)。
@Override
public Supplier<A> supplier() {
return supplier;
}
// 累加計(jì)算:累加流中的每一個元素T到A容器存儲的結(jié)果中,這里沒有返回值,所以A必須是容器,避免數(shù)據(jù)丟失
@Override
public BiConsumer<A, T> accumulator() {
return accumulator;
}
// 這里是當(dāng)開啟parallelStream()并發(fā)處理時,會得到多個結(jié)果容器A,這里對多個結(jié)果進(jìn)行合并
@Override
public BinaryOperator<A> combiner() {
return combiner;
}
// 這里是處理中間結(jié)果類型轉(zhuǎn)換成返回結(jié)果類型
@Override
public Function<A, R> finisher() {
return finisher;
}
// 這里標(biāo)記返回結(jié)果的數(shù)據(jù)類型,這里取值來自于Collector接口的內(nèi)部類Characteristics
@Override
public Set<Characteristics> characteristics() {
return characteristics;
}
}
enum Characteristics {
// 表示此收集器是 并發(fā)的 ,這意味著結(jié)果容器可以支持與多個線程相同的結(jié)果容器同時調(diào)用的累加器函數(shù)。
CONCURRENT,
// 表示收集操作不承諾保留輸入元素的遇到順序。
UNORDERED,
// 表示整理器功能是身份功能,可以被刪除。
IDENTITY_FINISH
}到此這篇關(guān)于springboot升級到j(luò)dk21的文章就介紹到這了,更多相關(guān)springboot升級到j(luò)dk21內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springboot集成SpringState狀態(tài)機(jī)的實(shí)現(xiàn)
本文主要介紹了Springboot集成SpringState狀態(tài)機(jī)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-06-06
解析springBoot-actuator項(xiàng)目構(gòu)造中health端點(diǎn)工作原理
這篇文章主要介紹了springBoot-actuator中health端點(diǎn)工作原理,對spring-boot-actuator的項(xiàng)目構(gòu)造,工作原理進(jìn)行了全面的梳理,側(cè)重health健康檢查部分2022-02-02
解決阿里代碼規(guī)范檢測中方法缺少javadoc注釋的問題
這篇文章主要介紹了解決阿里代碼規(guī)范檢測中方法缺少javadoc注釋的問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
springboot?vue測試平臺開發(fā)調(diào)通前后端環(huán)境實(shí)現(xiàn)登錄
這篇文章主要介紹了springboot?vue測試平臺開發(fā)調(diào)通前后端環(huán)境實(shí)現(xiàn)登錄詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
SpringBoot實(shí)現(xiàn)字段自動填充的兩種方式
每個字段在插入數(shù)據(jù)庫,或者更新時都要在serviceimpl層對creatby,updateby等字段進(jìn)行填充,這個太繁瑣了,所以本文給大家介紹了SpringBoot實(shí)現(xiàn)字段自動填充的兩種方式,需要的朋友可以參考下2024-11-11
SpringCloud分布式事務(wù)Seata部署和集成過程
這篇文章主要介紹了SpringCloud分布式事務(wù)Seata部署和集成過程,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-10-10

