国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

java stream實現(xiàn)分組BigDecimal求和,自定義分組求和

這篇具有很好參考價值的文章主要介紹了java stream實現(xiàn)分組BigDecimal求和,自定義分組求和。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

前言

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

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

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

@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進行求和

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ù)時常在分組后需要做一些判斷邏輯再進行累加業(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)我們自己的收集器。文章來源地址http://www.zghlxwxcb.cn/news/detail-790400.html

// 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é)果進行合并
        @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)于java stream實現(xiàn)分組BigDecimal求和,自定義分組求和的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Java stream 分組操作

    根據(jù)單/多字段分組 單字段分組可以直接使用指定字段,多字段分組則采用拼接Key的形式 單字段: 多字段: 多層級: 測試

    2024年02月15日
    瀏覽(24)
  • Java stream多字段分組(groupingBy)

    Java stream多字段分組(groupingBy)

    近期的項目里,遇到一個需求:對于含有多個元素的 ListPerson ,按照其中的某幾個屬性進行分組,比如 Persion::getAge 、 Persion::getType 、 Persion::getGender 等字段。下面就讓我們討論一下如何比較優(yōu)雅的按多字段進行分組groupingBy。 Stream 是Java8的一個新特性,主要用戶集合數(shù)據(jù)的處

    2024年02月13日
    瀏覽(25)
  • Java Stream流 Map 分組方式匯總

    java老式的分組方式(對list for循環(huán)然后 if判斷?放入map)?代碼復(fù)雜,易讀性差,維護性差,故本文匯總了Stream流中的分組方法供大家參考,如對您有幫助,請?zhí)Ц哔F的小手點個贊吧,歡迎大佬留下高見 (以下方法默認(rèn)都是java8的方法,java9新增方法有標(biāo)注) 按顏色分組 打印Map結(jié)果: {紅色

    2024年02月06日
    瀏覽(25)
  • Java Stream 處理分組后取每組最大&Stream流之list轉(zhuǎn)map、分組取每組第一條&Java 8 Collectors:reducing 示例(List分組取最值)

    Java Stream 處理分組后取每組最大&Stream流之list轉(zhuǎn)map、分組取每組第一條&Java 8 Collectors:reducing 示例(List分組取最值)

    有一個需求功能:先按照某一字段分組,再按照另外字段獲取最大的那個 先根據(jù)appId分組,然后根據(jù)versionSort取最大. JDK1.8推出的stream流能極大的簡化對集合的操作,讓代碼更美觀,老規(guī)矩,直接上代碼。 取list中對象的某個屬性作為唯一key,對象作為value形成一個map集合,能

    2024年02月16日
    瀏覽(27)
  • 【大數(shù)據(jù)Hive3.x數(shù)倉開發(fā)】窗口函數(shù)案例:連續(xù)N次登錄的用戶;級聯(lián)累加求和;分組TopN

    【大數(shù)據(jù)Hive3.x數(shù)倉開發(fā)】窗口函數(shù)案例:連續(xù)N次登錄的用戶;級聯(lián)累加求和;分組TopN

    對窗口函數(shù)的講解part見:【大數(shù)據(jù)Hive3.x數(shù)倉開發(fā)】函數(shù)–窗口函數(shù) 自連接過濾實現(xiàn) 連續(xù)兩天登陸的用戶ID: 窗口函數(shù)lead()實現(xiàn) 功能:用于從當(dāng)前數(shù)據(jù)中基于當(dāng)前行的數(shù)據(jù)向后偏移取值 語法: lead(colName,N,defautValue) colName:取哪一列的值 N:向后偏移N行 defaultValue:如果取不到返回

    2023年04月17日
    瀏覽(22)
  • Java Stream 實用特性:排序、分組和 teeing

    基本數(shù)據(jù)類型排序 基本數(shù)據(jù)類型就是字符串、整型、浮點型這些,也就是要排序的列表中的元素都是這些基本類型的,比如 ListInteger 的。 下面就用一個整型列表舉例說明。 正序排序 正序排序,也可以叫做按照自然順序排序,對于整型來說就是從小到大的。 輸出結(jié)果是 [0

    2024年02月03日
    瀏覽(21)
  • Java8 Stream 之groupingBy 分組講解

    本文主要講解:Java 8 Stream之Collectors.groupingBy()分組示例 Collectors.groupingBy() 分組之常見用法 功能代碼: /** ?? ? * 使用java8 stream groupingBy操作,按城市分組list ?? ? */ ?? ?public void groupingByCity() { ?? ??? ?MapString, ListEmployee map = employees.stream().collect(Collectors.groupingBy(Employee::getCi

    2024年02月13日
    瀏覽(25)
  • Java中用Stream分組并求各組數(shù)量

    Java中用Stream分組并求各組數(shù)量

    比如給了我一個班級的所有人的姓氏和姓名對象集合,根據(jù)這個集合求出各姓氏有多少人。直接上代碼。 User的實體類對象為 輸出的結(jié)果為: ? 即姓張的有3個,姓李的有兩個。 詳解:?將該集合的stream流用Collectors對象轉(zhuǎn)成Map,用User對象的firstName作為Key,默認(rèn)鍵值為1,在處

    2024年02月12日
    瀏覽(24)
  • Java8的stream之groupingBy()分組排序

    Java8的stream之groupingBy()分組排序

    groupingBy()是Stream API中最強大的收集器Collector之一,提供與SQL的GROUP BY子句類似的功能。 需要指定一個屬性才能使用,通過該屬性執(zhí)行分組。我們通過提供功能接口的實現(xiàn)來實現(xiàn)這一點 - 通常通過傳遞lambda表達式。 TreeMap默認(rèn)按照key升序排序,collectPlan.descendingMap()可以進行降序排

    2024年02月12日
    瀏覽(24)
  • Java 8 Stream實用篇,玩轉(zhuǎn)集合的篩選、歸約、分組、聚合

    Java 8 Stream實用篇,玩轉(zhuǎn)集合的篩選、歸約、分組、聚合

    Stream將要處理的元素集合看作一種流,在流的過程中,借助Stream API對流中的元素進行操作,比如:篩選、排序、聚合等。 Stream可以由數(shù)組或集合創(chuàng)建,對流的操作分為兩種: 中間操作 ,每次返回一個新的流,可以有多個。 終端操作 ,每個流只能進行一次終端操作,終端操

    2024年01月20日
    瀏覽(29)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包