最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

springboot升級到j(luò)dk21最新教程(2023年)

 更新時間:2023年10月27日 09:06:11   作者:JavaGPT  
你還在使用jdk8?快來看看最新出爐的SpringBoot+jdk21如何使用,下面這篇文章主要給大家介紹了關(guān)于springboot升級到j(luò)dk21的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

隨著微服務(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.實現(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.實現(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.實現(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.實現(xiàn)三

思路:業(yè)務(wù)時常在分組后需要做一些判斷邏輯再進(jìn)行累加業(yè)務(wù)計算,所以自己實現(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é)

自定義實現(xiàn)收集器可以參考Collectors的內(nèi)部類CollectorImpl的源碼,具體解析寫到注釋中。

推薦通過模仿Collectors.summingInt()的實現(xiàn)來實現(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ù)計算累加結(jié)果會丟失(累加結(jié)果不是通過返回值方式修改的)。
        @Override
        public Supplier<A> supplier() {
            return supplier;
        }
        
        // 累加計算:累加流中的每一個元素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)文章

  • Java中的線程私有變量ThreadLocal詳解

    Java中的線程私有變量ThreadLocal詳解

    這篇文章主要介紹了Java中的線程私有變量ThreadLocal詳解,ThreadLoalMap是ThreadLocal中的一個靜態(tài)內(nèi)部類,類似HashMap的數(shù)據(jù)結(jié)構(gòu),但并沒有實現(xiàn)Map接口,需要的朋友可以參考下
    2023-08-08
  • Mybatis防止sql注入原理分析

    Mybatis防止sql注入原理分析

    這篇文章主要介紹了Mybatis防止sql注入原理分析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • springboot 無法掃描到父類模塊中Bean的原因及解決

    springboot 無法掃描到父類模塊中Bean的原因及解決

    這篇文章主要介紹了springboot 無法掃描到父類模塊中Bean的原因及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Springboot使用RabbitMQ實現(xiàn)關(guān)閉超時訂單(示例詳解)

    Springboot使用RabbitMQ實現(xiàn)關(guān)閉超時訂單(示例詳解)

    介紹了如何在Spring Boot項目中使用RabbitMQ實現(xiàn)訂單的延時處理和超時關(guān)閉,通過配置RabbitMQ的交換機(jī)、隊列和綁定關(guān)系,以及編寫監(jiān)聽方法,實現(xiàn)了訂單數(shù)據(jù)的發(fā)送和延時消費(fèi),感興趣的朋友一起看看吧
    2025-01-01
  • 詳解Java8?StreamAPI中的map()方法

    詳解Java8?StreamAPI中的map()方法

    Stream?API?是Java8中新加入的功能,這篇文章主要帶大家了解一下?Stream?API?中的?map()?方法的使用,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-04-04
  • 使用IDEA搭建一個簡單的SpringBoot項目超詳細(xì)過程

    使用IDEA搭建一個簡單的SpringBoot項目超詳細(xì)過程

    這篇文章主要介紹了使用IDEA搭建一個簡單的SpringBoot項目超詳細(xì)過程,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • JFreeChart折線圖的生成方法

    JFreeChart折線圖的生成方法

    這篇文章主要為大家詳細(xì)介紹了JFreeChart折線圖的生成方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • java中的動態(tài)代理(jdk和Cglib)實現(xiàn)詳解

    java中的動態(tài)代理(jdk和Cglib)實現(xiàn)詳解

    這篇文章主要介紹了java中的動態(tài)代理(jdk和Cglib)的相關(guān)資料,本文通過實例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2025-04-04
  • Java servlet通過事件驅(qū)動進(jìn)行高性能長輪詢詳解

    Java servlet通過事件驅(qū)動進(jìn)行高性能長輪詢詳解

    這篇文章主要介紹了基于servlet3.0+事件驅(qū)動實現(xiàn)高性能長輪詢的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2022-06-06
  • Dubbo本地調(diào)試的幾種方式總結(jié)

    Dubbo本地調(diào)試的幾種方式總結(jié)

    dubbo服務(wù)方啟動時需要加載的東西太多,如果跑單元測試把服務(wù)開啟會浪費(fèi)不少時間,而且單元測試沒法保持服務(wù)一直開啟的狀態(tài),這篇文章主要給大家介紹了關(guān)于Dubbo本地調(diào)試的幾種方式,需要的朋友可以參考下
    2022-11-11

最新評論

武强县| 股票| 开化县| 金阳县| 潮州市| 临澧县| 龙胜| 永和县| 通州市| 含山县| 磐安县| 马尔康县| 汶上县| 榆林市| 陇西县| 沧州市| 兰溪市| 满城县| 江孜县| 册亨县| 三明市| 武安市| 元氏县| 洛川县| 绿春县| 三门峡市| 那坡县| 修武县| 九龙城区| 延边| 南宫市| 科尔| 轮台县| 眉山市| 厦门市| 图片| 久治县| 西畴县| 蓝山县| 桐城市| 成安县|