Java8之流Stream使用,附上例子

Posted zexzhang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java8之流Stream使用,附上例子相关的知识,希望对你有一定的参考价值。

package stream;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class steamMain {
    public static void main(String[] args) {
        /**
         * map函数
         * 将流中的每?个元素 T 映射为 R(类似类型转换)
         * 上堂课的例?就是,类似遍历集合,对集合的每个对象做处理
         * 场景:转换对象,如javaweb开发中集合??的DO对象转换为DTO对象
         */
        List<String> list = Arrays.asList("springboot教程", "微服务教程", "并发编程", "压?测试", "架构课程");
        List<String> li = Arrays.asList("asdad", "dfsfs", "erdsd", "zxcsdad", "weqqweqsd");

        List<String> resultlist = list.stream().map(obj -> "我想学习" + obj).collect(Collectors.toList());
        System.out.println(resultlist);

        List<user> list1 = Arrays.asList(new user(12, "123"), new user(23, "234"), new user(24, "345"));
        List<userDTO> resLIst = list1.stream().map(obj -> {
            userDTO user = new userDTO();
            user.setName(obj.getName());
            return user;
        }).collect(Collectors.toList());
        System.out.println(resLIst);

        /**
         * filter 函数
         * ?于通过设置的条件过滤出元素
         * 需求:过滤出字符串?度?于5的字符串
         */
        List<String> list2 = list.stream().filter(obj -> obj.length() > 4).collect(Collectors.toList());
        System.out.println(list2);

        /**
         * sorted 函数
         * sorted() 对流进??然排序, 其中的元素必须实现Comparable 接?
         */
        //默认升序
        //List<String> list4 = li.stream().sorted(Comparator.comparing(String::length)).collect(Collectors.toList());
        //反转 降序
        //List<String> list4 = li.stream().sorted(Comparator.comparing(String::length).reversed()).collect(Collectors.toList());
        List<String> list4 = li.stream().sorted(Comparator.comparing(String::length, Comparator.reverseOrder())).collect(Collectors.toList());
        System.out.println(list4);

        /**
         * limit函数
         * 截断流使其最多只包含指定数量的元素
         */
        List<String> list5 = li.stream().limit(3).collect(Collectors.toList());
        System.out.println(list5);

        /**
         * allMatch函数
         * 检查是否匹配所有元素,只有全部符合才返回true
         */
        boolean status = li.stream().allMatch(obj -> obj.length() > 4);
        System.out.println(status);

        /**
         * anyMatch函数
         * 检查是否?少匹配?个元素 只要又一个符合要求,返回true
         */
        boolean status1 = li.stream().anyMatch(obj -> obj.length() > 10);
        System.out.println(status1);


        /**
         * max函数
         */
        // Optional<user> list7 = list1.stream().max(Comparator.comparingInt(user::getAge));
        Optional<user> list7 = list1.stream().max((s1, s2) -> Integer.compare(s1.getAge(), s2.getAge()));
        System.out.println(list7.get().getAge());

        /**
         * min函数
         */
        //Optional<user> list8  =list1.stream().min(Comparator.comparingInt(user::getAge));
        Optional<user> list8 = list1.stream().min((s1, s2) -> Integer.compare(s1.getAge(), s2.getAge()));
        System.out.println(list8.get().getAge());

        /**
         * 并行流 parallelStream
         * 为什么会有这个并?流
         *   集合做重复的操作,如果使?串?执?会相当耗时,因此?般会采?多线程来加快, Java8的
         *   paralleStream?fork/join框架提供了并发执?能?
         * 底层原理
         *   线程池(ForkJoinPool)维护?个线程队列
         *   可以分割任务,将?任务拆分成?任务,完全贴合分治思想
         *
         * paralleStream并?是否?定?Stream串?快?
         *   错误,数据量少的情况,可能串?更快,ForkJoin会耗性能
         * 多数情况下并??串?快,是否可以都?并?
         *   不?,部分情况会有线程安全问题,parallelStream??使?的外部变量,?如集合?
         *   定要使?线程安全集合,不然就会引发多线程安全问题
         */
        //两种区别
        System.out.println("Stream输出集合");
        li.stream().forEach(System.out::println);
        System.out.println("parallelStream");
        li.parallelStream().forEach(System.out::println);

        //使用parallelStream有线程安全问题,所以集合对象需要集合安全的对象
        //循环10次
        for (int i = 0; i < 10; i++) {
            //arrayList的添加方法没有加锁,线程不安全
            //List paralleList = new ArrayList();
            List paralleList = new CopyOnWriteArrayList();
            //生成0到100的数,并行的加入到数组
            IntStream.range(0, 100).parallel().forEach(paralleList::add);
            //如果是用的是ArrayList 这里会报数组下标越界异常,原因ArrayLits的add方法没有加锁,循环到了第9次时,因为是多线程,查看size的时候,都同时加1了,导致下标越界。
            //换成CopyOnWriteArrayList集合则不会,因为CopyOnWriteArrayList集合的add方法有加锁
            System.out.println(paralleList.size());
        }

        /**
         * reduce操作
         * 什么是reduce操作
         *   聚合操作,中?意思是 “减少”
         *   根据?定的规则将Stream中的元素进?计算后返回?个唯?的值
         *   常??法?
         Optional<T> reduce(BinaryOperator<T> accumulator);
         */
        //累加器
        int value = Stream.of(1, 2, 3, 4, 5, 6).reduce((item1, item2) -> item1 + item2).get();
        System.out.println(value);
        //带起始值的累加器
        int value1 = Stream.of(1, 2, 3, 4, 5, 6).reduce(100, (item1, item2) -> item1 + item2);
        System.out.println(value1);

        //使用reduce求出最大值
        int value2 = Stream.of(213, 2312, 12, 454).reduce((item1, item2) -> item1 > item2 ? item1 : item2).get();
        System.out.println(value2);


        /**
         * foreach操作
         * 集合遍历的?式
         *   for循环
         *   迭代器 Iterator
         *
         * Jdk8??的新增接?
         *  default void forEach(Consumer<? super T> action) {
         *    Objects.requireNonNull(action);
         *    for (T t : this) {
         *      action.accept(t);
         *    }
         *  }
         *
         * 注意点
         *   不能修改包含外部的变量的值
         *   不能?break或者return或者continue等关键词结束或者跳过循环
         */
        list1.stream().forEach(obj -> System.out.println(obj));
        int totalAge = 0;
        //测试修改包含外部的变量的值
//        list1.stream().forEach(obj ->{
//            System.out.println(obj);
//            totalAge += obj.getAge();
//        });

        //测试?break或者return或者continue等关键词结束或者跳过循环
//        li.stream().forEach(obj ->{
//            System.out.println(obj);
//            return;
//        });


        /**
         * collector 收集器
         * ?个终端操作, ?于对流中的数据进?归集操作,collect?法接受的参数是?个Collector
         * 有两个重载?法,在Stream接???
         * default void forEach(Consumer<? super T> action) {
         *   Objects.requireNonNull(action);
         *   for (T t : this) {
         *     action.accept(t);
         *   }
         *  }
         * List<Student> results = Arrays.asList(new Student(32),new
         *  Student(33),new Student(21),new Student(29),new Student(18));
         * results.forEach(obj->{
         *  System.out.println(obj.toString());
         * });
         * Collector的作?
         *   就是收集器,也是?个接?, 它的?具类Collectors提供了很多???法
         * Collectors 的作?
         *   ?具类,提供了很多常?的收集器实现
         * Collectors.toList()
         * ArrayList::new,创建?个ArrayList作为累加器
         * List::add,对流中元素的操作就是直接添加到累加器中
         * reduce操作, 对?任务归集结果addAll,后?个?任务的结果直接全部添加到
         * 前?个?任务结果中
         * CH_ID 是?个unmodifiableSet集合
         * Collectors.toMap()
         * Collectors.toSet()
         * Collectors.toCollection() :??定义的实现Collection的数据结构收集
         * Collectors.toCollection(LinkedList::new)
         * Collectors.toCollection(CopyOnWriteArrayList::new)
         * Collectors.toCollection(TreeSet::new)
         */

        List<String> listStr = Stream.of("dsad", "dasdsa", "123dsa").collect(Collectors.toList());
        System.out.println(listStr);
        //set集合
        Set<String> setStr = Stream.of("dsad", "dasdsa", "123dsa", "123dsa").collect(Collectors.toSet());
        System.out.println(setStr);
        Set<String> setStr1 = Stream.of("dsad", "dasdsa", "123dsa", "123dsa").collect(Collectors.toCollection(TreeSet::new));
        System.out.println(setStr1);
        List<String> listStr1 = Stream.of("dsad", "dasdsa", "123dsa", "123dsa").collect(Collectors.toCollection(ArrayList::new));
        System.out.println(listStr1);

        /**
         * join函数
         * 拼接函数 Collectors.joining
         *  //重载?法?
         *  <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T>
         * accumulator, BiConsumer<R, R>combiner);
         *  //重载?法?
         *  <R, A> R collect(Collector<? super T, A, R> collector);
         * public static <T> Collector<T, ?, List<T>> toList() {
         * return new CollectorImpl<>((Supplier<List<T>>)
         * ArrayList::new, List::add,(left, right) -> {
         * left.addAll(right); return left; }, CH_ID);
         * }
         * 其中?个的实现
         * 说明:
         * 该?法可以将Stream得到?个字符串, joining函数接受三个参数,分别表示 元素之间的连
         * 接符、前缀和后缀。
         */
        //将数组集合"||"拼接在一起
        String value3 = list.stream().collect(Collectors.joining("||"));
        System.out.println(value3);
        //还可以使用join函数,指定前缀和后缀
        String value4 = list.stream().collect(Collectors.joining("||", "{", "}"));
        System.out.println(value4);

        /**
         * partitioningBy分组
         * Collectors.partitioningBy 分组,key是boolean类型
         * public static <T>
         * Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super
         * T> predicate) {
         *  return partitioningBy(predicate, toList());
         * }
         */
        //将数组长度大于5的字符串分出来
        Map<Boolean,List<String>> boMap = li.stream().collect(Collectors.partitioningBy(obj -> obj.length() > 5));
        boMap.forEach((k,v) ->{
            System.out.println(k+"->"+v);
        });


        /**
         * groupby 分组
         * 分组 Collectors.groupingBy()
         * public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<?
         * super T, ? extends K> classifier) { return groupingBy(classifier, toList());
         * }
         */

        //练习:根据学?所在的省份,进?分组

        List<Student> studentList = Arrays.asList(new Student("?东", 23), new
                Student("?东", 24), new Student("?东", 23),new Student("北京", 22), new
                Student("北京", 20), new Student("北京", 20),new Student("海南", 25));

        Map<String,List<Student>> stuMap = studentList.stream().collect(Collectors.groupingBy(obj -> obj.getProvince()));
        stuMap.forEach((k,v)->{
            System.out.println(k+"有"+v);
        });

        //算出每个地区有多少人
        /**
         * 分组统计,groupby分组进阶
         * 分组后进行统计Collectors.counting() 统计元素个数
         */
        Map<String,Long> longMap = studentList.stream().collect(Collectors.groupingBy(obj -> obj.getProvince(),Collectors.counting()));
        longMap.forEach((k,v)->{
            System.out.println(k+"有"+v+"人");
        });

        /**
         * groupby分组进阶
         * summarizing集合统计
         * 作?:可以?个?法把统计相关的基本上都完成
         * 分类
         *   summarizingInt
         *   summarizingLong
         *   summarizingDouble
         */
        IntSummaryStatistics summaryStatistics = studentList.stream().collect(Collectors.summarizingInt(obj -> obj.getAge()));
        System.out.println("平均年龄"+summaryStatistics.getAverage());
        System.out.println("总人数"+summaryStatistics.getCount());
        System.out.println("最大年龄"+summaryStatistics.getMax());
        System.out.println("最小年龄"+summaryStatistics.getMin());




    }
}
package stream;

public class Student {

    private String province;
    private int age;

    public Student() {
    }

    public Student(String province, int age) {
        this.province = province;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "province=‘" + province + ‘‘‘ +
                ", age=" + age +
                ‘}‘;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
package stream;

public class user {

    private int age;
    private String name;

    public user(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public user() {
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "user{" +
                "age=" + age +
                ", name=‘" + name + ‘‘‘ +
                ‘}‘;
    }
}
package stream;

public class userDTO {

    private String name;

    public userDTO(String name) {
        this.name = name;
    }

    public userDTO() {
    }

    public String getName() {
        return name;
    }

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

 

以上是关于Java8之流Stream使用,附上例子的主要内容,如果未能解决你的问题,请参考以下文章

Java 8 stream 实战

Java8 Stream流

java8 stream, map, Option 等函数式编程的使用例子

java8 stream, map, Option 等函数式编程的使用例子

Java8初体验Stream语法详解

Java8 Stream针对List先分组再求和最大值最小值平均值等