stream基础知识

stream简介

Java8中的Stream是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作,或者大批量数据操作等操作;Stream不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的。

stream的创建

public static void main(String[] args) {
        //通过Collection系列集合通过的stream()或parallelStream()方法生成流
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        //创建串行流
        Stream<String> collectionStream = list.stream();
        //创建并行流
        Stream<String> collectionParallelStream = list.parallelStream();

        //通过Arrays中的静态方法stream()获取数组流
        Integer[] arrays = new Integer[]{1,2,3};
        Stream<Integer> arraysStream = Arrays.stream(arrays);

        //通过Stream类中的静态方法of()获取流
        Stream<Object> stream = Stream.of(1, "a");

        //无限流(可以无限生成数据的流)
        /**
         * 迭代
         * 第一个参数表示初始值,
         * 第二个参数是接口是函数,表示生成什么样的数据,
         * 本例是生成偶数据
         */

        Stream<Integer> iterateStream = Stream.iterate(0, (e) -> e + 2);

        //生成
        Stream<Double> generateStream = Stream.generate(() -> Math.random());

Stream的操作

Stream的操作有中间操作和终止操作2中类型操作;

中间操作只会处理数据,不会生成结果;
终止操作是终止中间操作并且生成中间操作后的数据。

Stream的中间操作

准备数据

public class User {
    private String name;
    private Integer age;
    private Double money;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

    public User(String name, Integer age, Double money) {
        this.name = name;
        this.age = age;
        this.money = money;
    }

    public User() {
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", money=" + money +
                '}';
    }

    /**
     * 如果不同时重写equals和hashCode方法,则distinct方法无效
     * 
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;
        User user = (User) o;
        return Objects.equals(getName(), user.getName()) &&
                Objects.equals(getAge(), user.getAge());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getName(), getAge());
    }
}

	static List<User> userList = new ArrayList<>();
    static {

        userList.add(new User("张三",20,1000D));
        userList.add(new User("李四",21,2000D));
        userList.add(new User("王五",22,3000D));
        userList.add(new User("赵六",23,4000D));
        userList.add(new User("张三",20,2000D));

    }

filter(筛选操作)

public static void main(String[] args) {
        /**
         * filter(筛选)
         * 参数:接收一个接口式函数 ,改函数是进行条件判断的,表示筛选出满足改条件的数据
         * 数据会内部迭代,筛选全部数据
         */

        Stream<User> userStream = userList.stream().filter(e -> e.getAge() > 22);
        //输出筛选后的数据
        userStream.forEach(System.out::println);
        
    }

limit(截断流,使其元素不超过给定数量)

public static void main(String[] args) {

        /**
         * limit:截断流,使其元素不超过给定数量
         */
        Stream<User> userStream = userList.stream().limit(3);
        //输出筛选后的数据
        userStream.forEach(System.out::println);

    }

skip

public static void main(String[] args) {

        /**
         * skip:跳过元素,返回一个舍弃了前n个元素的流;
         *      若流中元素不足n个,则返回一个空流;
         *      
         */
        Stream<User> userStream = userList.stream().skip(2);
        //输出筛选后的数据
        userStream.forEach(System.out::println);

    }

limit和skip组合成分页功能

public static void main(String[] args) {

        /**
         * 使用skip和limit组合成分页
         *
         */
        Integer page = 0;
        Integer rows = 2;
        Integer start = page * rows;
        if(start > userList.size()){
            start = userList.size() - rows;
        }
        Stream<User> userStream = userList.stream().skip(start).limit(rows);
        //输出筛选后的数据
        userStream.forEach(System.out::println);
    }

filter与limit和skip组合的区别

public static void main(String[] args) {


        /**
         * filter和limit组合会终止数据的内部迭代,
         * 当数据筛选数据个数满足limit的个数时,数据就会终止迭代
         */
        Stream<User> limitUserStream = userList.stream().filter(e -> {
            System.out.println("1111");
            return e.getAge() > 19;
        }).limit(1);
        //输出筛选后的数据
        limitUserStream.forEach(System.out::println);

        /**
         * filter和skip组合不会终止数据的内部迭代,
         * 他是在筛选出所有的数据后,在跳过skip指定的个数
         */
        Stream<User> skipUserStream = userList.stream().filter(e -> {
            System.out.println("2222");
            return e.getAge() > 19;
        }).skip(1);
        //输出筛选后的数据
        skipUserStream.forEach(System.out::println);

    }

distinct(去重)

public static void main(String[] args) {

        /**
         * distinct:去重,当集合数据为类对象时,
         *          改对象必须重写hashCode()与equals()方法,
         *          否则无法去重
         *
         */
        //类对象集合
        Stream<User> userStream = userList.stream().distinct();
        //输出筛选后的数据
        userStream.forEach(System.out::println);
        //基本数据集合
        List<Integer> integerList = new ArrayList<>();
        integerList.add(1);
        integerList.add(1);
        Stream<Integer> distinctInteger = integerList.stream().distinct();
        distinctInteger.forEach(System.out::println);
        //基本数据集合
        List<String> stringList = new ArrayList<>();
        stringList.add("a");
        stringList.add("a");
        Stream<String> distinctString = stringList.stream().distinct();
        distinctString.forEach(System.out::println);

    }

map(映射)

public static void main(String[] args) {

        /**
         * map:接收接口式函数作为参数,
         *      该函数会被应用到每个元素上,
         *      并将其映射成一个新的元素
         *
         */
        //获取用户姓名
        Stream<String> userNameStream = userList.stream().map(e -> e.getName());
        //输出筛选后的数据
        userNameStream.forEach(System.out::println);
    }

flatMap(拍平映射)

public static void main(String[] args) {

        /**
         * flatMap:接收接口式函数作为参数,
         *      该函数会被应用到每个元素上,
         *      并将每个元素换成另一个流,
         *      然后把所有流重新连接成一个流其映射成一个新的元素
         *
         */
        //获取用户姓名中的子的集合
        Stream<Character> userNameStream = userList.stream().map(User::getName).flatMap(e ->{
            List<Character> list = new ArrayList<>();
            for (Character ch : e.toCharArray()){
                list.add(ch);
            }
            return list.stream();
        });
        userNameStream.forEach(System.out::println);
    }

sorted(排序)

public static void main(String[] args) {
public static void main(String[] args) {
        /**
         * sorted:排序;接受一个接口式函数作为参数,改函数用于指明排序规则
         */
        Stream<User> sortedUser = userList.stream().sorted((first, second) -> {
            Integer firstAge = first.getAge();
            Integer secondAge = second.getAge();
            int i = firstAge - secondAge;
            if (i == 0) {

                String firstName = first.getName();
                String secondName = second.getName();
                i = firstName.hashCode() - secondName.hashCode();
            }
            return i;
        });
        
        sortedUser.forEach(System.out::println);
    }
终止操作

allMatch、anyMatch和noneMatch匹配

public static void main(String[] args) {
        /**
         * allMatch:全部匹配
         *          匹配流中所有元素是否都满足条件;
         *          如果都满足条件,则返回true;
         *          否则返回false
         */
        boolean allMatchFlag = userList.stream().allMatch(e -> e.getAge() == 20);
        System.out.println("allMatchFlag:"+allMatchFlag);

        /**
         * anyMatch:任意匹配
         *          匹配流中任意元素是否满足条件;
         *          如果有一个元素满足条件,则返回true;
         *          否则返回false
         */
        boolean anyMatchFlag = userList.stream().anyMatch(e -> e.getAge() == 20);
        System.out.println("anyMatchFlag:"+anyMatchFlag);


        /**
         * noneMatchFlag:都不匹配
         *          匹配流中所有元素是否满足条件;
         *          如果都不满足条件,则返回true;
         *          否则返回false
         */
        boolean noneMatchFlag = userList.stream().noneMatch(e -> e.getAge() == 200);
        System.out.println("noneMatchFlag:"+noneMatchFlag);

    }

findFirst和findAny查找

 public static void main(String[] args) {
        /**
         * findFirst:获取流中第一个元素;
         *          串行流和并行流的结果都一样
         */
        Optional<User> opFirst = userList.stream().findFirst();

        if(opFirst.isPresent()){
            User user = opFirst.get();
            System.out.println(user);
        }

        /**
         * findAny:获取流中的任意一个元素; 
         *          串行流最会获取第一个元素,
         *          并行流会随机获取任意一个元素
         *          
         */
        for (int i = 0; i < 100; i++){
            Optional<User> opAnyFirst = userList.stream().findAny();

            if(opAnyFirst.isPresent()){
                User user = opAnyFirst.get();
                System.out.println(user);
            }
        }

        for (int i = 0; i < 100; i++){
            Optional<User> opAnySecond = userList.parallelStream().findAny();

            if(opAnySecond.isPresent()){
                User user = opAnySecond.get();
                System.out.println(user);
            }
        }
    }

count、max和min

public static void main(String[] args) {


        //获取流中是总个数
        long count = userList.stream().count();
        System.out.println("count:"+count);
        //获取流中年龄最大的用户
        Optional<User> maxOP = userList.stream().max((first, second) -> Double.compare(first.getAge(), second.getAge()));
        if(maxOP.isPresent()){
            User user = maxOP.get();
            System.out.println(user);
        }

        //获取流中年龄最小的年龄值
        Optional<Integer> minOP = userList.stream().map(e -> e.getAge()).min(Double::compare);
        if(maxOP.isPresent()){
            Integer minAge = minOP.get();
            System.out.println(minAge);
        }

    }

reduce

public static void main(String[] args) {
        /**
         *  reduce:可以将流中的数据结合起来,得到一个值;
         *      第一个参数表示初始值,
         *      第二个参数是接口式函数,要出来这些数据的逻辑
         */
        
        Double reduce = userList.stream().map(e -> e.getMoney()).reduce(0d, (x, y) -> x + y);
        System.out.println(reduce);
        /**
         * 由于没有指定初始值,所以返回Optional对象
         */
        Optional<Double> reduceOp = userList.stream().map(e -> e.getMoney()).reduce(Double::sum);
        if(reduceOp.isPresent()){
            System.out.println(reduceOp.get());
        }
    }

collect(收集)

public static void main(String[] args) {
        /**
         * joining:将收集后的数据所有","路径起来
         */
        String str = userList.stream().map(e -> e.getName()).collect(Collectors.joining(","));
        System.out.println(str);

        /**
         * toSet:将收集的数据转成Set集合
         */
        Set<String> set = userList.stream().map(e -> e.getName()).collect(Collectors.toSet());
        System.out.println(set);
        /**
         * toCollection:将收集的数据转成HashSet集合
         */
        Set<String> hashSet = userList.stream().map(e -> e.getName()).collect(Collectors.toCollection(HashSet::new));
        System.out.println(hashSet);

        /**
         * toMap:将收集的数据转成map集合
         *      第一个参数是接口式函数,表示生成key值策略;
         *      第二个参数是接口式函数,表示生成value的策略;
         *      第三个参数是接口是函数,表示当key重复了,如何生成key-value的策略,
         *      此处表示使用新的value退回以前的value
         */
        Map<String, Double> map = userList.stream().collect(Collectors.toMap(e -> e.getName(), e -> e.getMoney(),(oldVal, currVal) -> currVal));
        System.out.println(map);

    }

计算

public static void main(String[] args) {
        /**
         * counting:计算数据数据的总个数
         */
        Long count = userList.stream().collect(Collectors.counting());
        System.out.println("count:"+count);

        /**
         * summingDouble:求和
         */
        Double sum = userList.stream().collect(Collectors.summingDouble(e -> e.getMoney()));
        System.out.println("sum:"+sum);

        /**
         * averagingDouble:求平均值
         */
        Double average = userList.stream().collect(Collectors.averagingDouble(e -> e.getMoney()));
        System.out.println("average:"+average);

        /**
         * 获取工资最高的用户
         */
        Optional<User> maxOp = userList.stream().collect(Collectors.maxBy((first, second) -> Double.compare(first.getMoney(), second.getMoney())));
        if(maxOp.isPresent()){
            System.out.println("maxUser:"+maxOp.get());
        }

        /**
         * 获取最低工资值
         */
        Optional<Double> minOp = userList.stream().map(e -> e.getMoney()).collect(Collectors.minBy(Double::compare));
        if(minOp.isPresent()){
            System.out.println("min"+minOp.get());
        }


        System.out.println("----------------------");
        /**
         * summarizingDouble:总结
         */
        DoubleSummaryStatistics dss = userList.stream().collect(Collectors.summarizingDouble(User::getMoney));
        System.out.println("max:"+dss.getMax());
        System.out.println("count:"+dss.getCount());
        System.out.println("min:"+dss.getMin());
        System.out.println("average:"+dss.getAverage());
        System.out.println("sum:"+dss.getSum());

    }

分组

public static void main(String[] args) {

        /**
         * 单一分组
         */
        Map<Integer, List<User>> groupCollect = userList.stream().collect(Collectors.groupingBy(User::getAge));
        System.out.println(groupCollect);

        /**
         * 自定义分组
         */
        Map<String, Map<String, List<User>>> zdyGroupCollect = userList.stream().collect(Collectors.groupingBy(User::getName, Collectors.groupingBy(e -> {
            if (e.getAge() <= 10) {
                return "儿童";
            } else if (e.getAge() <= 18) {
                return "青年";
            } else {
                return "非青年";
            }
        })));
        System.out.println(zdyGroupCollect);
        /**
         * 多级分组
         */
        Map<String, Map<Integer, List<User>>> moreGroupCollect = userList.stream().collect(Collectors.groupingBy(User::getName, Collectors.groupingBy(User::getAge)));
        System.out.println(moreGroupCollect);

    }

分区

public static void main(String[] args) {
        Map<Boolean, List<User>> collect = userList.stream().collect(Collectors.partitioningBy(e -> e.getMoney() > 2000));
        System.out.println(collect);
    }

串行流与并行流

public static void main(String[] args) {

        /**
         * sequential:改方法可以就流转换成串行流(相当于集合创建的串行流),
         *              该流只会使用一个线程去执行;
         * parallel:改方法可以就流转换成并行流(相当于集合创建的并行流),
         *              该流会调用多个线程去执行。
         */
        //串行流
        Instant sequentialStart = Instant.now();
        long sequentialResult = LongStream.rangeClosed(0, 100000000000l).sequential().reduce(0, Long::sum);//
        Instant sequentialEnd = Instant.now();
        System.out.println("串行流耗时:"+Duration.between(sequentialStart, sequentialEnd).toMillis());
        System.out.println(sequentialResult);

        //并行流
        Instant parallelStart = Instant.now();
        long parallelResult = LongStream.rangeClosed(0, 100000000000l).parallel().reduce(0, Long::sum);//4891
        Instant parallelEnd = Instant.now();
        System.out.println("并行流耗时:"+Duration.between(parallelStart, parallelEnd).toMillis());
        System.out.println(parallelResult);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值