Collectors.groupingBy、Collectors.mapping的使用


1.Collectors.groupingBy、Collectors.mapping:

參考博客:https://blog.csdn.net/L_fly_J/article/details/120164362

Person.java:

package com.mayikt.entity;

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
}
View Code

測試代碼:

package com.mayikt.stream;

import com.mayikt.entity.Person;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class TestCollectorsMapping {
    public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person("Ram", 30));
        list.add(new Person("Shyam", 20));
        list.add(new Person("Shiv", 20));
        list.add(new Person("Mahesh", 30));

        String nameByAge = list.stream().collect(Collectors.mapping(Person::getName, Collectors.joining(",", "[", "]")));
        System.out.println(nameByAge);
        nameByAge = list.stream().map(person -> person.getName()).collect(Collectors.joining(",", "[", "]"));
        System.out.println(nameByAge);

        Map<Integer, String> nameByAgeMap = list.stream().collect(
                Collectors.groupingBy(Person::getAge, Collectors.mapping(Person::getName, Collectors.joining(",", "[", "]"))));
        nameByAgeMap.forEach((k, v) -> System.out.println("Age:" + k + "  Persons: " + v));

        Map<Integer, List<String>> map2 = list.stream().collect(
                Collectors.groupingBy(Person::getAge, Collectors.mapping(Person::getName, Collectors.toList())));
        System.out.println(map2);
    }
}
[Ram,Shyam,Shiv,Mahesh]
[Ram,Shyam,Shiv,Mahesh]
可以發現達到相同的效果

Age:20  Persons: [Shyam,Shiv]
Age:30  Persons: [Ram,Mahesh]
封裝為Map后返回

{20=[Shyam, Shiv], 30=[Ram, Mahesh]}

 

2、Collectors.groupingBy的使用例子2:

查看代碼

package com.mayikt.entity;

public class UserAuth {
    public String channelId;
    public String authType;

    public UserAuth(String channelId, String authType) {
        this.channelId = channelId;
        this.authType = authType;
    }

    public String getChannelId() {
        return channelId;
    }

    public String getAuthType() {
        return authType;
    }

    @Override
    public String toString() {
        return "UserAuth{" +
                "channelId='" + channelId + '\'' +
                ", authType='" + authType + '\'' +
                '}';
    }
}

測試類:

package com.mayikt.stream;

import com.mayikt.entity.UserAuth;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class TestCollectorsGroupBy {

    /**
     * 假如有用戶認證,認證在渠道 + 認證方式上。
     * 現在想把這些數據,按照authType分組作為map的key,將渠道歸集成list作為map的value,怎么做?
     * @param args
     */
    public static void main(String[] args) {
        List<UserAuth> list = new ArrayList<>();
        list.add(new UserAuth("EIBS", "B"));
        list.add(new UserAuth("EMBS", "B"));
        list.add(new UserAuth("EIBS", "K"));

        Map<String, List<String>> authChannelMap0 =
                list.stream().collect(Collectors.groupingBy(UserAuth::getAuthType, Collectors.mapping(UserAuth::getChannelId, Collectors.toList())));
        System.out.println(authChannelMap0);

        Map<String, String> authChannelMap2 =
                list.stream().collect(Collectors.groupingBy(UserAuth::getAuthType, Collectors.mapping(UserAuth::getChannelId, Collectors.joining(",", "[", "]"))));
        System.out.println(authChannelMap2);
    }
}

console:

{B=[EIBS, EMBS], K=[EIBS]}
{B=[EIBS,EMBS], K=[EIBS]}

 

3.Collectors.groupingBy的三個方法

參考博客: https://blog.csdn.net/HO1_K/article/details/127572093

Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier)
Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream)
Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier, Supplier<M> mapFactory, Collector<? super T, A, D> downstream)

classifier:鍵映射:該方法的返回值是鍵值對的 鍵
mapFactory:無參構造函數提供返回類型:提供一個容器初始化方法,用於創建新的 Map容器 (使用該容器存放值對)。
downstream:值映射:通過聚合方法將同鍵下的結果聚合為指定類型,該方法返回的是鍵值對的 值。

代碼示例:

Order:

查看代碼
 package com.model;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

/**
 * @description com.model
 * @author: chengyu
 * @date: 2023-10-08 19:25
 */
@Getter
@Setter
@ToString
@AllArgsConstructor
public class Order {
    /**
     * 機構號
     */
    private Long deptSeq;

    /**
     * 訂單號
     */
    private String orderNo;

    /**
     * 訂單金額
     */
    private String amount;
}
package com.test.lamdba;

import com.model.Order;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

public class TestGroupingBy {

    /**
     * 將訂單列表按機構號分組
     * groupingBy有三個方法
     */
    public static void main(String[] args) {
        List<Order> orderList = new ArrayList<>();
        orderList.add(new Order(340000L, "orderNo_001", "10"));
        orderList.add(new Order(340101L, "orderNo_002", "20"));
        orderList.add(new Order(340309L, "orderNo_003", "5"));
        orderList.add(new Order(340309L, "orderNo_004", "12"));

        /**
         * 將訂單按照機構號分組
         * groupingBy的一個參數的方法,mapFactory是使用HashMap的,所以無序  值默認是ArrayList
         */
        Map<Long, List<Order>> orderMap1 = orderList.stream().collect(Collectors.groupingBy(Order::getDeptSeq));
        orderMap1.forEach((k, v) -> System.out.println("deptSeq:" + k + "  Orders: " + v));

        /**
         * 將訂單按照機構號分組
         * groupingBy的兩個參數的方法,指定了downstream
         */
        Map<Long, String> orderMap2 = orderList.stream().collect(Collectors.groupingBy(Order::getDeptSeq, Collectors.mapping(Order::getOrderNo, Collectors.joining(","))));
        orderMap2.forEach((k, v) -> System.out.println("deptSeq:" + k + "  Orders: " + v));

        /**
         * 將訂單按照機構號分組,並且有序(原來list的順序)
         * groupingBy的三個參數的方法,指定了mapFactory和downstream
         */
        Map<Long, List<Order>> orderMap3 = orderList.stream().collect(Collectors.groupingBy(Order::getDeptSeq, TreeMap::new, Collectors.toList()));
        orderMap3.forEach((k, v) -> System.out.println("deptSeq:" + k + "  Orders: " + v));
    }
}
deptSeq:340309  Orders: [Order(deptSeq=340309, orderNo=orderNo_003, amount=5), Order(deptSeq=340309, orderNo=orderNo_004, amount=12)]
deptSeq:340101  Orders: [Order(deptSeq=340101, orderNo=orderNo_002, amount=20)]
deptSeq:340000  Orders: [Order(deptSeq=340000, orderNo=orderNo_001, amount=10)]

deptSeq:340309  Orders: orderNo_003,orderNo_004
deptSeq:340101  Orders: orderNo_002
deptSeq:340000  Orders: orderNo_001

deptSeq:340000  Orders: [Order(deptSeq=340000, orderNo=orderNo_001, amount=10)]
deptSeq:340101  Orders: [Order(deptSeq=340101, orderNo=orderNo_002, amount=20)]
deptSeq:340309  Orders: [Order(deptSeq=340309, orderNo=orderNo_003, amount=5), Order(deptSeq=340309, orderNo=orderNo_004, amount=12)]

tips:  

1.保證分組后的有序性的話,也可以自定義容器類型為LinkedHashMap。

2.也可以根據鍵的值,生成不同的范圍,這種范圍類型的鍵多數情況下都是通過比較來生成的,常用於統計指標,如:

查看代碼
 // 根據兩級范圍 將學生划分及格不及格兩類
Map<Boolean, List<Student>> customRangeKey = students.stream().collect(Collectors.groupingBy(student -> student.getScore() > 60));
// 根據多級范圍 根據學生成績來評分
Map<String, List<Student>> customMultiRangeKey = students.stream().collect(Collectors.groupingBy(student -> {
    if (student.getScore() < 60) {
        return "C";
    } else if (student.getScore() < 80) {
        return "B";
    }
    return "A";
}));

3.分組統計功能,Collectors.counting:計數 

查看代碼
// 計數
Map<String, Long> groupCount = students.stream().collect(Collectors.groupingBy(Student::getCourse, Collectors.counting()));

 

 

 

 

----


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM