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

java?stream實(shí)現(xiàn)分組BigDecimal求和以及自定義分組求和

 更新時(shí)間:2023年12月09日 09:53:12   作者:只愛編碼  
這篇文章主要給大家介紹了關(guān)于java?stream實(shí)現(xiàn)分組BigDecimal求和以及自定義分組求和的相關(guān)資料,Stream是Java8的一大亮點(diǎn),是對(duì)容器對(duì)象功能的增強(qiáng),它專注于對(duì)容器對(duì)象進(jìn)行各種非常便利、高效的聚合操作或者大批量數(shù)據(jù)操作,需要的朋友可以參考下

前言

隨著微服務(wù)的發(fā)展,越來越多的sql處理被放到j(luò)ava來處理,數(shù)據(jù)庫經(jīng)常會(huì)使用到對(duì)集合中的數(shù)據(jù)進(jìn)行分組求和,分組運(yùn)算等等。
那怎么樣使用java的stream優(yōu)雅的進(jìn)行分組求和或運(yùn)算呢?

一、準(zhǔn)備測(cè)試數(shù)據(jù)

這里測(cè)試數(shù)據(jù)學(xué)生,年齡類型是Integer,身高類型是BigDecimal,我們分別對(duì)身高個(gè)年齡進(jìn)行求和。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    /**
     * 姓名
     */
    private String name;
    /**
     * 年齡
     */
    private Integer age;
    /**
     * 身高
     */
    private BigDecimal stature;
}

public class LambdaLearn {
	// 初始化的測(cè)試數(shù)據(jù)集合
    static List<Student> list = new ArrayList<>();

    static {
    // 初始化測(cè)試數(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沒有封裝對(duì)應(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ù)時(shí)常在分組后需要做一些判斷邏輯再進(jìn)行累加業(yè)務(wù)計(jì)算,所以自己實(shí)現(xiàn)一個(gè)收集器

1.封裝一個(gè)自定義收集器

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, // 將多個(gè)容器結(jié)果合并成一個(gè)
                      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.封裝一個(gè)函數(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是中間處理臨時(shí)保存類型,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);
        }

		// 這里提供一個(gè)初始化的容器,用于存儲(chǔ)每次累加。即使我們求和這里也只能使用容器存儲(chǔ),否則后續(xù)計(jì)算累加結(jié)果會(huì)丟失(累加結(jié)果不是通過返回值方式修改的)。
        @Override
        public Supplier<A> supplier() {
            return supplier;
        }
        
        // 累加計(jì)算:累加流中的每一個(gè)元素T到A容器存儲(chǔ)的結(jié)果中,這里沒有返回值,所以A必須是容器,避免數(shù)據(jù)丟失
        @Override
        public BiConsumer<A, T> accumulator() {
            return accumulator;
        }
        
        // 這里是當(dāng)開啟parallelStream()并發(fā)處理時(shí),會(huì)得到多個(gè)結(jié)果容器A,這里對(duì)多個(gè)結(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é)果容器可以支持與多個(gè)線程相同的結(jié)果容器同時(shí)調(diào)用的累加器函數(shù)。 
    CONCURRENT,

// 表示收集操作不承諾保留輸入元素的遇到順序。
    UNORDERED,
    
// 表示整理器功能是身份功能,可以被刪除。 
    IDENTITY_FINISH
}

補(bǔ)充例子:求相同姓名的學(xué)生的年齡之和(姓名組合)

package com.TestStream;
 
import java.util.*;
import java.util.stream.Collectors;
 
/**
 * @author 林高祿
 * @create 2020-06-09-9:29
 */
public class Demo2 {
    public static void main(String[] args) {
        List<Student> studentList = StudentUtil2.createStudentList();
        // 通過姓名分組,姓名為key,相同姓名的學(xué)生為列表
        Map<String, List<Student>> collect = studentList.stream().collect(Collectors.groupingBy(Student::getName, Collectors.toList()));
        // collect的數(shù)據(jù)為
        System.out.println("collect的數(shù)據(jù)為:");
        collect.forEach((key,list)-> {
            System.out.println("key:"+key);
            list.forEach(System.out::println);
        });
        // 分組后的年齡和為
        System.out.println("分組后的年齡和為:");
        collect.forEach((key,list)-> System.out.println("key:"+key+",年齡和"+list.stream().mapToInt(Student::getAge).sum()));
 
    }
 
}

運(yùn)行輸出:

collect的數(shù)據(jù)為:
key:陳文文
Student{no=1, name='陳文文', age=10, mathScore=100.0, chineseScore=90.0}
Student{no=2, name='陳文文', age=20, mathScore=90.0, chineseScore=70.0}
key:林高祿
Student{no=1, name='林高祿', age=20, mathScore=90.5, chineseScore=90.5}
Student{no=11, name='林高祿', age=20, mathScore=90.5, chineseScore=90.5}
Student{no=2, name='林高祿', age=10, mathScore=80.0, chineseScore=90.0}
Student{no=1, name='林高祿', age=30, mathScore=90.5, chineseScore=90.0}
key:1林高祿
Student{no=1, name='1林高祿', age=20, mathScore=90.5, chineseScore=90.5}
key:蔡金鑫
Student{no=1, name='蔡金鑫', age=30, mathScore=80.0, chineseScore=90.0}
分組后的年齡和為:
key:陳文文,年齡和30
key:林高祿,年齡和80
key:1林高祿,年齡和20
key:蔡金鑫,年齡和30

到此這篇關(guān)于java stream實(shí)現(xiàn)分組BigDecimal求和以及自定義分組求和的文章就介紹到這了,更多相關(guān)java stream分組BigDecimal求和內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Java的TCP/IP編程學(xué)習(xí)--基于定界符的成幀

    詳解Java的TCP/IP編程學(xué)習(xí)--基于定界符的成幀

    這篇文章主要介紹了Java的TCP/IP編程學(xué)習(xí)--基于定界符的成幀,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Java中的ThreadLocalMap源碼解讀

    Java中的ThreadLocalMap源碼解讀

    這篇文章主要介紹了Java中的ThreadLocalMap源碼解讀,ThreadLocalMap是ThreadLocal的內(nèi)部類,是一個(gè)key-value數(shù)據(jù)形式結(jié)構(gòu),也是ThreadLocal的核心,需要的朋友可以參考下
    2023-09-09
  • SpringBoot全局異常與數(shù)據(jù)校驗(yàn)的方法

    SpringBoot全局異常與數(shù)據(jù)校驗(yàn)的方法

    這篇文章主要介紹了SpringBoot全局異常與數(shù)據(jù)校驗(yàn)的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-11-11
  • 基于springboot設(shè)置Https請(qǐng)求過程解析

    基于springboot設(shè)置Https請(qǐng)求過程解析

    這篇文章主要介紹了基于springboot設(shè)置Https請(qǐng)求過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Java經(jīng)典面試題匯總:JVM

    Java經(jīng)典面試題匯總:JVM

    本篇總結(jié)的是JVM相關(guān)的面試題,后續(xù)會(huì)持續(xù)更新,希望我的分享可以幫助到正在備戰(zhàn)面試的實(shí)習(xí)生或者已經(jīng)工作的同行,如果發(fā)現(xiàn)錯(cuò)誤還望大家多多包涵,不吝賜教,謝謝
    2021-07-07
  • SpringBoot自動(dòng)裝配注解的實(shí)現(xiàn)示例

    SpringBoot自動(dòng)裝配注解的實(shí)現(xiàn)示例

    本文主要介紹了SpringBoot自動(dòng)裝配注解的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-04-04
  • JAVA中HTTP基本認(rèn)證(Basic Authentication)實(shí)現(xiàn)

    JAVA中HTTP基本認(rèn)證(Basic Authentication)實(shí)現(xiàn)

    HTTP 基本認(rèn)證是一種簡單的認(rèn)證方法,本文主要介紹了JAVA中HTTP基本認(rèn)證(Basic Authentication),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-07-07
  • Java關(guān)鍵字、標(biāo)識(shí)符、常量、變量語法詳解

    Java關(guān)鍵字、標(biāo)識(shí)符、常量、變量語法詳解

    這篇文章主要為大家詳細(xì)介紹了Java關(guān)鍵字、標(biāo)識(shí)符、常量、變量等基礎(chǔ)語法,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Java集合總結(jié)

    Java集合總結(jié)

    今天小編就為大家分享一篇關(guān)于Java集合總結(jié),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • 配置了jdk的環(huán)境idea卻提示找不到j(luò)dk解決辦法

    配置了jdk的環(huán)境idea卻提示找不到j(luò)dk解決辦法

    在使用Java編程語言進(jìn)行開發(fā)時(shí),IDEA是一個(gè)非常流行和強(qiáng)大的集成開發(fā)環(huán)境,這篇文章主要給大家介紹了關(guān)于配置了jdk的環(huán)境idea卻提示找不到j(luò)dk的解決辦法,需要的朋友可以參考下
    2023-12-12

最新評(píng)論

石嘴山市| 上虞市| 灌云县| 周口市| 墨竹工卡县| 于都县| 鄄城县| 浦北县| 靖边县| 贡觉县| 六盘水市| 麻阳| 石渠县| 福州市| 唐海县| 钟山县| 新乡县| 衡水市| 茂名市| 孝义市| 芦山县| 和林格尔县| 安丘市| 千阳县| 康平县| 确山县| 紫阳县| 锡林浩特市| 柳江县| 射阳县| 河源市| 扶风县| 林西县| 彭泽县| 田林县| 西乡县| 怀来县| 宁海县| 武平县| 辉县市| 都江堰市|