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

Java?Stream實現(xiàn)多字段分組groupingBy操作詳解

 更新時間:2023年06月08日 08:47:48   作者:草率小猿  
Stream是Java8的一個新特性,主要用戶集合數(shù)據(jù)的處理,如排序、過濾、去重等等功能,本文就來講講如何利用Stream實現(xiàn)比較優(yōu)雅的按多字段進行分組groupingBy吧

近期的項目里,遇到一個需求:對于含有多個元素的List<Person>,按照其中的某幾個屬性進行分組,比如Persion::getAge、Persion::getType、Persion::getGender等字段。下面就讓我們討論一下如何比較優(yōu)雅的按多字段進行分組groupingBy。

利用Stream進行分組

Stream是Java8的一個新特性,主要用戶集合數(shù)據(jù)的處理,如排序、過濾、去重等等功能,這里我們不展開講解。本文主要講解的是利用Stream.collect()來對List進行分組。

Person類Person.java:

public class Person {
    /**
     * id
     */
    private Integer id;
    /**
     * 年齡
     */
    private Integer age;
    /**
     * 類型
     */
    private String type;
    /**
     * 姓名
     */
    private String name;
    /**
     * 性別
     */
    private String gender;
    public Integer getId() {
        return id;
    }
    public Person setId(Integer id) {
        this.id = id;
        return this;
    }
    public Integer getAge() {
        return age;
    }
    public Person setAge(Integer age) {
        this.age = age;
        return this;
    }
    public String getType() {
        return type;
    }
    public Person setType(String type) {
        this.type = type;
        return this;
    }
    public String getName() {
        return name;
    }
    public Person setName(String name) {
        this.name = name;
        return this;
    }
    public String getGender() {
        return gender;
    }
    public Person setGender(String gender) {
        this.gender = gender;
        return this;
    }
}

1. 利用單個字段進行分組

如上面的Person類,如果對于其中的某一個字段進行分組(如gender),則比較簡單,我們可以利用Stream.collect()Collectors.groupingBy結(jié)合,即可進行分組groupingBy,代碼如下:

public class TestGroupingBy {
    public static void main(String[] args) {
        List<Person> personList = Arrays.asList(
                new Person().setId(1).setAge(18).setType("student").setName("user - 1").setGender("male"),
                new Person().setId(2).setAge(20).setType("student").setName("user - 2").setGender("male"),
                new Person().setId(3).setAge(18).setType("student").setName("user - 3").setGender("male"),
                new Person().setId(4).setAge(18).setType("student").setName("user - 4").setGender("male"),
                new Person().setId(5).setAge(35).setType("teacher").setName("user - 5").setGender("male"),
                new Person().setId(6).setAge(35).setType("teacher").setName("user - 6").setGender("male"),
                new Person().setId(7).setAge(20).setType("student").setName("user - 7").setGender("male"),
                new Person().setId(8).setAge(20).setType("student").setName("user - 8").setGender("female"),
                new Person().setId(9).setAge(20).setType("student").setName("user - 9").setGender("female"),
                new Person().setId(10).setAge(20).setType("student").setName("user - 10").setGender("female")
        );
        Map<String, List<Person>> groupingMap = personList.stream().collect(Collectors.groupingBy(Person::getGender));
}

其中的groupingMap ,類型為Map<String, List<Person>>,第一個泛型為String即分組字段(本例中為gender字段)的類型,第二個泛型為List<Person>及分組結(jié)果的類型。

我們在Debug模式下運行代碼,可以看到groupingMap 數(shù)據(jù)如下:

可以看到personList數(shù)據(jù)按照gender屬性被分成了兩組。

2. 利用多個字段進行分組

上面的例子是按單個字段分組,如果需要按照多個字段,如gender、age、type三個字段進行分組,同樣也可以可以利用Stream.collect()Collectors.groupingBy結(jié)合的方式進行分組,不過該方式中調(diào)用Collectors.groupingBy時需要多次嵌套調(diào)用,測試代碼如下:

public class TestGroupingBy {
    public static void main(String[] args) {
        List<Person> personList = Arrays.asList(
                new Person().setId(1).setAge(18).setType("student").setName("user - 1").setGender("male"),
                new Person().setId(2).setAge(20).setType("student").setName("user - 2").setGender("male"),
                new Person().setId(3).setAge(18).setType("student").setName("user - 3").setGender("male"),
                new Person().setId(4).setAge(18).setType("student").setName("user - 4").setGender("male"),
                new Person().setId(5).setAge(35).setType("teacher").setName("user - 5").setGender("male"),
                new Person().setId(6).setAge(35).setType("teacher").setName("user - 6").setGender("male"),
                new Person().setId(7).setAge(20).setType("student").setName("user - 7").setGender("male"),
                new Person().setId(8).setAge(20).setType("student").setName("user - 8").setGender("female"),
                new Person().setId(9).setAge(20).setType("student").setName("user - 9").setGender("female"),
                new Person().setId(10).setAge(20).setType("student").setName("user - 10").setGender("female")
        );
        // 多字段嵌套分組
        Map<String, Map<Integer, Map<String, List<Person>>>> groupingMap = personList.stream().collect(
                Collectors.groupingBy(Person::getGender, 
                        Collectors.groupingBy(Person::getAge, 
                                Collectors.groupingBy(Person::getType)
                        )
                )
        );
    }
}

其中groupingMap類型為Map<String, Map<Integer, Map<String, List<Person>>>>,是一個嵌套了三層的Map,對應(yīng)的泛型String/Integer/String分別為對應(yīng)分組字段的類型,最后一層Map的value類型為List<Person>為實際分組后的數(shù)據(jù)集合類型,為方便查看數(shù)據(jù),特意按Json格式貼出數(shù)據(jù)如下:

{
  "female": {
    "20": {
      "student": [
        {
          "id": 8,
          "age": 20,
          "type": "student",
          "name": "user - 8",
          "gender": "female"
        },
        {
          "id": 9,
          "age": 20,
          "type": "student",
          "name": "user - 9",
          "gender": "female"
        },
        {
          "id": 10,
          "age": 20,
          "type": "student",
          "name": "user - 10",
          "gender": "female"
        }
      ]
    }
  },
  "male": {
    "18": {
      "student": [
        {
          "id": 1,
          "age": 18,
          "type": "student",
          "name": "user - 1",
          "gender": "male"
        },
        {
          "id": 3,
          "age": 18,
          "type": "student",
          "name": "user - 3",
          "gender": "male"
        },
        {
          "id": 4,
          "age": 18,
          "type": "student",
          "name": "user - 4",
          "gender": "male"
        }
      ]
    },
    "20": {
      "student": [
        {
          "id": 2,
          "age": 20,
          "type": "student",
          "name": "user - 2",
          "gender": "male"
        },
        {
          "id": 7,
          "age": 20,
          "type": "student",
          "name": "user - 7",
          "gender": "male"
        }
      ]
    },
    "35": {
      "teacher": [
        {
          "id": 5,
          "age": 35,
          "type": "teacher",
          "name": "user - 5",
          "gender": "male"
        },
        {
          "id": 6,
          "age": 35,
          "type": "teacher",
          "name": "user - 6",
          "gender": "male"
        }
      ]
    }
  }
}

可以看到,原先的List數(shù)據(jù),按照gender/age/type三個屬性,分成了三層的Map,對于這種多層的Map代碼上處理起來會有一些不方便。并且如果分組字段更多的話,所嵌套的Collectors.groupingBy也會更加多,代碼書寫起來也不太優(yōu)雅。

下面將介紹另外一種按多字段分組的方法。

3. 利用Collectors.groupingBy與Function結(jié)合進行多字段分組

查看Collectors.groupingByAPI會發(fā)現(xiàn),其中一種用法是第一個參數(shù)為Function,如下:

簡單翻譯一下就是:一種將輸入元素映射到鍵的分類函數(shù)。即需要定義一個函數(shù)Function,該函數(shù)將元素對象映射到一個鍵的集合里。代碼示例如下:

public class TestGroupingBy {
    public static void main(String[] args) {
        List<Person> personList = Arrays.asList(
                new Person().setId(1).setAge(18).setType("student").setName("user - 1").setGender("male"),
                new Person().setId(2).setAge(20).setType("student").setName("user - 2").setGender("male"),
                new Person().setId(3).setAge(18).setType("student").setName("user - 3").setGender("male"),
                new Person().setId(4).setAge(18).setType("student").setName("user - 4").setGender("male"),
                new Person().setId(5).setAge(35).setType("teacher").setName("user - 5").setGender("male"),
                new Person().setId(6).setAge(35).setType("teacher").setName("user - 6").setGender("male"),
                new Person().setId(7).setAge(20).setType("student").setName("user - 7").setGender("male"),
                new Person().setId(8).setAge(20).setType("student").setName("user - 8").setGender("female"),
                new Person().setId(9).setAge(20).setType("student").setName("user - 9").setGender("female"),
                new Person().setId(10).setAge(20).setType("student").setName("user - 10").setGender("female")
        );
        // 定義一個函數(shù)Function,該函數(shù)將元素對象映射到一個鍵的集合里
        Function<Person, List<Object>> compositeKey = person ->
                Arrays.asList(person.getGender(), person.getAge(), person.getType());
        // 分組
        Map<List<Object>, List<Person>> groupingMap =
                personList.stream().collect(Collectors.groupingBy(compositeKey, Collectors.toList()));
    }
}

通過在Debug模式下運行代碼,可以看到groupingMap的數(shù)據(jù)結(jié)構(gòu)如下:

groupingMap數(shù)據(jù)僅僅只有一層,但是其鍵值Key卻是一個List,里面包含了分組字段的值,如上圖中的male、35、teacher是集合中屬性gender/age/type分別是male、35teacher的元素集合。數(shù)據(jù)按Json格式貼出如下:

{
  "[male, 35, teacher]": [
    {
      "id": 5,
      "age": 35,
      "type": "teacher",
      "name": "user - 5",
      "gender": "male"
    },
    {
      "id": 6,
      "age": 35,
      "type": "teacher",
      "name": "user - 6",
      "gender": "male"
    }
  ],
  "[female, 20, student]": [
    {
      "id": 8,
      "age": 20,
      "type": "student",
      "name": "user - 8",
      "gender": "female"
    },
    {
      "id": 9,
      "age": 20,
      "type": "student",
      "name": "user - 9",
      "gender": "female"
    },
    {
      "id": 10,
      "age": 20,
      "type": "student",
      "name": "user - 10",
      "gender": "female"
    }
  ],
  "[male, 20, student]": [
    {
      "id": 2,
      "age": 20,
      "type": "student",
      "name": "user - 2",
      "gender": "male"
    },
    {
      "id": 7,
      "age": 20,
      "type": "student",
      "name": "user - 7",
      "gender": "male"
    }
  ],
  "[male, 18, student]": [
    {
      "id": 1,
      "age": 18,
      "type": "student",
      "name": "user - 1",
      "gender": "male"
    },
    {
      "id": 3,
      "age": 18,
      "type": "student",
      "name": "user - 3",
      "gender": "male"
    },
    {
      "id": 4,
      "age": 18,
      "type": "student",
      "name": "user - 4",
      "gender": "male"
    }
  ]
}

由于Map只有一層,用該方式分組的結(jié)果,對于我們業(yè)務(wù)也是比較友好,代碼里對數(shù)據(jù)處理起來也是比較方便的。可以看到,從代碼書寫角度以及分組處理后得到的結(jié)果,該方法都是最優(yōu)雅的。

寫在最后

可以看到,如果分組字段只有一個,我們可以用比較簡單的利用Stream.collect()Collectors.groupingBy進行處理,但對于多個字段的分組操作,建議還是用Collectors.groupingByFunction進行處理。

到此這篇關(guān)于Java Stream實現(xiàn)多字段分組groupingBy操作詳解的文章就介紹到這了,更多相關(guān)Java Stream分組內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

诏安县| 泰州市| 崇义县| 郑州市| 崇礼县| 霍邱县| 专栏| 临西县| 罗山县| 庆城县| 利川市| 吉安县| 石阡县| 霍林郭勒市| 嫩江县| 石阡县| 嘉定区| 灌南县| 井陉县| 清河县| 永登县| 柳州市| 会东县| 湾仔区| 肃北| 固镇县| 莒南县| 远安县| 汉阴县| 祁门县| 新化县| 神池县| 葫芦岛市| 双江| 得荣县| 淮阳县| 虞城县| 铜山县| 梅州市| 临沭县| 雅安市|