Java8——Stream流的使用(收集操作)(三)

public static <T,U,A,R> Collector<T,?,R> mapping(Function<? super T,? extends U> mapper, Collector<? super U,A,R> downstream)

3. 转换

3.1 转换收集

public static <T,U,A,R> Collector<T,?,R> mapping(Function<? super T,? extends U> mapper, Collector<? super U,A,R> downstream)

  mapper:对每一个流元素都应用的一元函数,返回的值将被作为downstream收集器的初始流元素!
  downstream:一个收集器,对转换之后的流元素进行收集操作。
  返回一个Collector。mapping方法首先将元素流元素分别应用一元函数转换为相应的数据,然后再使用一个收集器对这些数据进行收集。类似于Stream的map+collect方法的结合。
  在上面的集合操作中可能用不到该方法,因为我们可以先直接调用Srteam的map方法转换之后再收集。但是在后面的分组和分区方法中,却是非常的有用,后面会讲到!

3.2 收集转换

public static <T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream, Function<R,RR> finisher)

  downstream:一个收集器,对流元素进行收集操作。
  finisher:对每一个收集结果都应用的一元函数,返回的值将被作为最终返回值!
返回一个Collector。collectingAndThen方法首先对流元素进行收集,然后再使用一个一元函数对这些收集结果进行运算,最后返回运算后的结果。

  可以看到,mapping和collectingAndThen方法是相反的,前一个先转换然后收集,后一个先收集然后转换!

3.3 使用案例
/**
 * @author lx
 */
public class MappingTest {
    /**
     * mapping
     * 类似于 map + collect
     */
    @Test
    public void mappingTest() {
        //收集全部学生分数ArrayList集合
        System.out.println(students.stream().collect(mapping(Student::getScore, toList())));
        //收集全部学生分数HashSet集合
        System.out.println(students.stream().collect(mapping(Student::getScore, toSet())));
        //收集全部学生分数LinkedHashSet集合
        LinkedHashSet<Integer> collect = students.stream().collect(mapping(Student::getScore,
                toCollection(LinkedHashSet::new)));
        System.out.println(collect);

        //收集全部学生分数的总和
        System.out.println(students.stream().collect(mapping(Student::getScore, reducing(0, Integer::sum))));
    }


    /**
     * collectingAndThen
     */
    @Test
    public void collectingAndThenTest() {
        //收集全部学生总数
        Integer collect = students.stream().collect(collectingAndThen(toList(), List::size));
        System.out.println(collect);

        //收集全部学生分数的总和
        Integer collect2 = students.stream().collect(collectingAndThen(mapping(Student::getScore, reducing(Integer::sum)), Optional::get));
        System.out.println(collect2);
    }


    List<Student> students = new ArrayList<>();

    @Before
    public void before() {
        students.add(new Student(1, 55, "小花"));
        students.add(new Student(2, 100, "小华"));
        students.add(new Student(3, 85, "晓华"));
        students.add(new Student(4, 70, "肖华"));
        students.add(new Student(5, 70, "小小"));
        students.add(new Student(6, 66, "小小"));
        students.add(new Student(7, 60, "小夏"));
        students.add(new Student(8, 77, "花花"));
    }


    static class Student {
        private int id;
        private int score;
        private String name;

        public int getId() {
            return id;
        }

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

        public int getScore() {
            return score;
        }

        public void setScore(int score) {
            this.score = score;
        }

        public String getName() {
            return name;
        }

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

        public Student(int id, int score, String name) {
            this.id = id;
            this.score = score;
            this.name = name;
        }

        public Student(int id) {
            this.id = id;
        }

        @Override
        public String toString() {
            return "Student{" +
                    "age=" + id +
                    ", score=" + score +
                    ", name='" + name + '\'' +
                    '}';
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof Student)) return false;

            Student student = (Student) o;

            if (getId() != student.getId()) return false;
            if (getScore() != student.getScore()) return false;
            return getName() != null ? getName().equals(student.getName()) : student.getName() == null;
        }

        @Override
        public int hashCode() {
            int result = getId();
            result = 31 * result + getScore();
            result = 31 * result + (getName() != null ? getName().hashCode() : 0);
            return result;
        }
    }
}
  • 4. 分组

      前面的集合操作中,我们可以通过toMap等方法将每一个元素通过指定的函数映射成为map的key和value,但有时候我们需要对一批数据根据某些属性进行一个总体的分组,而不是简单对每一个元素都进行操作,此时我们可以使用分组操作!
      Collectos的groupingBy静态方法定义了将流元素进行分组的收集器!有了这些方法,我们可以方便快捷的实现集合分组!这个名字看起来就像sql分组操作group by一样,Stream中分组操作和sql中的分组的意义都差不多!

    4.1 分组到Map

    public static <T,K> Collector<T,?,Map<K,List< T >>> groupingBy(Function<? super T,? extends K> classifier)

      classifier:一个分组函数。参数是每一个流元素,返回的值作为生成的map的key,流中具有相同返回值(key)的所有元素组成的List列表作为value。
      返回一个Collector,它将元素分组收集到一个Map,key是通过分组函数对流元素进行计算返回的结果,value是具备相同返回结果(key)的流元素List集合。实际Map类型是一个HashMap,线程不安全;实际value类型是一个ArrayList,线程不安全。

    public static <T,K,A,D> Collector<T,?,Map<K,D>> groupingBy(Function<? super T,? extends K> classifier, Collector<? super T,A,D> downstream)

      classifier:一个分组函数。参数是每一个流元素,返回的值作为生成的map的key,流中具有相同返回值(key)的所有元素组成的List列表作为value。
      downstream:一个收集器,用于指定将返回相同的key的流元素收起到一起的规则,比如指定使用什么集合作为value、甚至使用一个归纳操作等等!这里就可以使用mapping方法对原始流数据进行进一步处理之后再收集,完成更加细致的工作!
      返回一个Collector,它将元素分组收集到一个Map,key是通过分组函数对流元素进行计算返回的结果,value是具备相同返回结果(key)的流元素应用downstream收集器返回的结果。实际Map类型是一个HashMap,线程不安全;实际value类型根据downstream收集器的类型来确定。

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

      classifier:一个分组函数。参数是每一个流元素,返回的值作为生成的map的key,流中具有相同返回值(key)的所有元素组成的List列表作为value。
      mapFactory:一个生产者,用于指定集合实际类型,只要是Map体系中的集合!
      downstream:一个收集器,用于指定将返回相同的key的流元素收起到一起的规则,比如指定使用什么集合作为value、甚至使用一个归纳操作等等!这里就可以使用mapping方法对原始流数据进行进一步处理之后再收集,完成更加细致的工作!
      返回一个Collector,它将元素分组收集到一个Map,key是通过分组函数对流元素进行计算返回的结果,value是具备相同返回结果(key)的流元素应用downstream收集器返回的结果。实际Map类型是自己指定的,要求是Map体系中的集合;实际value类型根据downstream收集器的类型来确定。

    4.2 分组到ConcurrentMap

    public static <T,K> Collector<T,?,ConcurrentMap<K,List< T >>> groupingByConcurrent(Function<? super T,? extends K> classifier)

      classifier:一个分组函数。参数是每一个流元素,返回的值作为生成的map的key,流中具有相同返回值(key)的所有元素组成的List列表作为value。
      返回一个Collector,它将元素分组收集到一个Map,key是通过分组函数对流元素进行计算返回的结果,value是具备相同返回结果(key)的流元素List集合。实际Map类型是一个ConcurrentHashMap,线程安全;实际value类型是一个ArrayList,线程不安全。

    public static <T,K,A,D> Collector<T,?,ConcurrentMap<K,D>> groupingByConcurrent(Function<? super T,? extends K> classifier, Collector<? super T,A,D> downstream)

      classifier:一个分组函数。参数是每一个流元素,返回的值作为生成的map的key,流中具有相同返回值(key)的所有元素组成的List列表作为value。
      downstream:一个收集器,用于指定将返回相同的key的流元素收起到一起的规则,比如指定使用什么集合作为value、甚至使用一个归纳操作等等!这里就可以使用mapping方法对原始流数据进行进一步处理之后再收集,完成更加细致的工作!
      返回一个Collector,它将元素分组收集到一个Map,key是通过分组函数对流元素进行计算返回的结果,value是具备相同返回结果(key)的流元素应用downstream收集器返回的结果。实际Map类型是一个ConcurrentHashMap,线程安全;实际value类型根据downstream收集器的类型来确定。

    public static <T,K,A,D,M extends ConcurrentMap<K,D>> Collector<T,?,M> groupingByConcurrent(Function<? super T,? extends K> classifier, Supplier< M > mapFactory, Collector<? super T,A,D> downstream)

      classifier:一个分组函数。参数是每一个流元素,返回的值作为生成的map的key,流中具有相同返回值(key)的所有元素组成的List列表作为value。
      mapFactory:一个生产者,用于指定集合实际类型,只要是ConcurrentMap体系中的集合!
      downstream:一个收集器,用于指定将返回相同的key的流元素收起到一起的规则,比如指定使用什么集合作为value、甚至使用一个归纳操作等等!这里就可以使用mapping方法对原始流数据进行进一步处理之后再收集,完成更加细致的工作!
      返回一个Collector,它将元素分组收集到一个Map,key是通过分组函数对流元素进行计算返回的结果,value是具备相同返回结果(key)的流元素应用downstream收集器返回的结果。实际Map类型是自己指定的,要求是ConcurrentMap体系中的集合,线程安全;实际value类型根据downstream收集器的类型来确定。

    全文链接:Java8——Stream流的使用(收集操作)

  • 发表于 2020-09-16 16:47
  • 阅读 ( 20 )

0 条评论

请先 登录 后评论
NX小编
NX小编

995 篇文章

作家榜 »

  1. NX小编 995 文章
  2. 58沈剑 309 文章
  3. 奈学教育 131 文章
  4. 李希沅 | 奈学教育 28 文章
  5. 江帅帅 | 奈学教育 27 文章
  6. 林淮川 | 奈学教育 12 文章
  7. 科技热点 10 文章
  8. 邱鹏超 2 文章