avatar

list<E>分组成Map处理方法

任务的描述如下:

1
list<E>分组成Map<K,List<E>>方式

比如一个班级的学生,分成多个小组,目前查出来的数据是list的集合

  1. 我们拥有的原始数据集合
    1
    List<Person> allStudent = new LinkedList<>();
  2. 需要把结果处理成
    1
    Map<Integer, List<Person>>`
  3. 我们处理的方式使用
1
Collectors.toMap()
  1. 这个方法的原始描述
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    /**
    * Returns a {@code Collector} that accumulates elements into a
    * {@code Map} whose keys and values are the result of applying the provided
    * mapping functions to the input elements.
    *
    * <p>If the mapped
    * keys contain duplicates (according to {@link Object#equals(Object)}),
    * the value mapping function is applied to each equal element, and the
    * results are merged using the provided merging function.
    *
    * <p>There are no guarantees on the type, mutability, serializability,
    * or thread-safety of the {@code Map} returned.
    *
    * @apiNote
    * There are multiple ways to deal with collisions between multiple elements
    * mapping to the same key. The other forms of {@code toMap} simply use
    * a merge function that throws unconditionally, but you can easily write
    * more flexible merge policies. For example, if you have a stream
    * of {@code Person}, and you want to produce a "phone book" mapping name to
    * address, but it is possible that two persons have the same name, you can
    * do as follows to gracefully deal with these collisions, and produce a
    * {@code Map} mapping names to a concatenated list of addresses:
    * <pre>{@code
    * Map<String, String> phoneBook
    * = people.stream().collect(
    * toMap(Person::getName,
    * Person::getAddress,
    * (s, a) -> s + ", " + a));
    * }</pre>
    *
    * @implNote
    * The returned {@code Collector} is not concurrent. For parallel stream
    * pipelines, the {@code combiner} function operates by merging the keys
    * from one map into another, which can be an expensive operation. If it is
    * not required that results are merged into the {@code Map} in encounter
    * order, using {@link #toConcurrentMap(Function, Function, BinaryOperator)}
    * may offer better parallel performance.
    *
    * @param <T> the type of the input elements
    * @param <K> the output type of the key mapping function
    * @param <U> the output type of the value mapping function
    * @param keyMapper a mapping function to produce keys
    * @param valueMapper a mapping function to produce values
    * @param mergeFunction a merge function, used to resolve collisions between
    * values associated with the same key, as supplied
    * to {@link Map#merge(Object, Object, BiFunction)}
    * @return a {@code Collector} which collects elements into a {@code Map}
    * whose keys are the result of applying a key mapping function to the input
    * elements, and whose values are the result of applying a value mapping
    * function to all input elements equal to the key and combining them
    * using the merge function
    *
    * @see #toMap(Function, Function)
    * @see #toMap(Function, Function, BinaryOperator, Supplier)
    * @see #toConcurrentMap(Function, Function, BinaryOperator)
    */
    public static <T, K, U>
    Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
    Function<? super T, ? extends U> valueMapper,
    BinaryOperator<U> mergeFunction) {
    return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
    }
    解释下参数的含义,keyMapper 就是map的 key,valueMapper 就是map的value,mergeFunction这里我们
    1
    2
    3
    4
    (List<Person> newValueList, List<Person> oldValueList) -> {
    oldValueList.addAll(newValueList);
    return oldValueList;
    })
    把newValueList 放到oldValueList,返回值是oldValueList,实现了通过key筛选,然后value的list不断增加。最终实现分组
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    package com.wzl.day22;

    import com.alibaba.fastjson.JSON;

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

    public class Day22 {

    static class Person {
    private int id;
    private String name;
    /**
    * 用户所在的组
    */
    private int groupId;

    public int getId() {
    return id;
    }

    public void setId(int id) {
    this.id = id;
    }

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public int getGroupId() {
    return groupId;
    }

    public void setGroupId(int groupId) {
    this.groupId = groupId;
    }

    public Person(int id, String name, int groupId) {
    this.id = id;
    this.name = name;
    this.groupId = groupId;
    }
    }

    public static void main(String[] args) {
    // 4个学生在两个分组内
    Person p1 = new Person(1, "wu", 1);
    Person p2 = new Person(2, "zhi", 1);
    Person p3 = new Person(3, "de", 2);
    Person p4 = new Person(4, "xiao", 2);
    List<Person> allStudent = new LinkedList<>();
    allStudent.add(p1);
    allStudent.add(p2);
    allStudent.add(p3);
    allStudent.add(p4);

    String jsonStr = JSON.toJSONString(allStudent);
    System.out.println(jsonStr);
    // 以组id为key,Person为value
    Map<Integer, List<Person>> studentMap = allStudent.stream().collect(Collectors.toMap(
    key -> key.getGroupId(),
    val -> {
    List<Person> valList = new ArrayList();
    valList.add(val);
    return valList;
    },
    (List<Person> newValueList, List<Person> oldValueList) -> {
    oldValueList.addAll(newValueList);
    return oldValueList;
    }));

    String res = JSON.toJSONString(studentMap);
    System.out.println(res);

    }

    }
    效果如下;
1
2
3

[{"groupId":1,"id":1,"name":"wu"},{"groupId":1,"id":2,"name":"zhi"},{"groupId":2,"id":3,"name":"de"},{"groupId":2,"id":4,"name":"xiao"}]
{1:[{"groupId":1,"id":2,"name":"zhi"},{"groupId":1,"id":1,"name":"wu"}],2:[{"groupId":2,"id":4,"name":"xiao"},{"groupId":2,"id":3,"name":"de"}]}

可以清晰的看到原本的list,被分成了以groupid分组的map集合。

文章作者: 无知的小狼
文章链接: https://bytedance.press/2020/03/05/list%E5%88%86%E7%BB%84%E6%88%90Map/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 无知的小狼

评论