Java研学-Stream

一 Stream

1 概述

  JDK8的特性之一,并不是传统意义上的IO流,而是一个用于数据传输的"管道",他的作用是提供一组高效的操作数据的方法 – 针对集合中的数据

2 应用Stream对象

通常筛选集合中元素的方法

public class Play {
    public static void main(String[] args) {
        // 定义集合存放元素
        List<String> names= Arrays.asList("大黄","大白","小小黑");
        findNameLength(names);
        findNameByBig(names);
    }
    // 获取名字长度大于2的且名字中含有小字的动物
    private static void findNameLength(List<String> names){
        // 创建存放所有名字的集合
        List<String> n=new ArrayList<>();
        // 遍历筛选
        for (String s:names) {
            if(s.length()>2){
                n.add(s);
            }
        }
        // 筛选名字中有小的
        List<String> l=new ArrayList<>();
        for (String s:n) {
            if(s.contains("小")){
                l.add(s);
            }
        }
        System.out.println(l);
    }
    // 显示以大开头的动物
    private static void findNameByBig(List<String> names){
        List<String> n=new ArrayList<>();
        for (String s:names) {
            if(s.startsWith("大")){
                n.add(s);
            }
        }
        System.out.println(n);
    }
}

当过滤条件过多时,可使用Stream对象提供的方法,简化操作

public class Play {
    public static void main(String[] args) {
        // 定义集合存放元素
        List<String> names= Arrays.asList("大黄","大白","小小黑");
        findNameLength(names);
        findNameByBig(names);
    }
    // 获取名字长度大于2的且名字中含有小字的动物
    private static void findNameLength(List<String> names){
        names.stream()
                .filter(s->s.contains("小"))
                .filter(s->s.length()>2)
                .forEach(System.out::println);
    }
    // 显示以大开头的动物
    private static void findNameByBig(List<String> names){
        // 将集合转为Stream  集合类提供
        // public Stream<T> stream()
        // Stream<String> stream = names.stream();
        // 通过Stream对象调用过滤方法,此方法会遍历集合中的元素
        // public Stream<T> filter(Predocate<T> pre)
        //Stream<String> n = stream.filter(new Predicate<String>() {
        // @Override
        // public boolean test(String s) {
        //     return s.startsWith("大");
        // }
        // });
        // 通过Stream对象调用方法展示数据
        // n.forEach(System.out::println);
        names.stream()
                .filter(s -> s.startsWith("大"))
                .forEach(System.out::println);
    }
}

3 操作步骤

  核心点:将集合对象转换成Stream对象

  ① 转换成Stream对象

  ② 根据需求,调用Stream对象中的方法完成操作

  ③ 展示数据

  操作指定元素序列(集合或数组,集合居多)中符合指定要求(根据需求通过Stream对象调用方法完成对元素操作)的元素(集合或者数组中的数据)的一种技术

二 创建Stream对象的方式

1 共有五种

// 有限流
Collection默认的stream()方法和paralleStream()方法
Arrays.stream()
Stream.of()
// 无限流
Stream.iterate()
Stream.generate()

2 例子

public class Play {
    public static void main(String[] args) {
        // 方式1:单列集合转Stream
        // stream() 按集合中的顺序操作
        // paralleStream() 随机顺序进行操作
        List<String> list= Arrays.asList("大黄","大白","小黑");
        list.stream().forEach(System.out::println);
        list.parallelStream().forEach(System.out::println);
        // 方式2:数组转Stream
        Arrays.stream(new int[]{-2,-1,0,8,42}).forEach(System.out::println);
        // 方式3:将任意类型的多个数据视为一个整体转换为Stream
        Stream.of(false,10L,8,3.14,'@',"dwd").forEach(System.out::println);
        // 方式4:无限流 seed从指定数字计步 uo计步规则 配合limit(long size)可限定数据个数
        // Stream.iterate(T need,UnaryOperator<T> uo)
        /*Stream.iterate(1, new UnaryOperator<Integer>() {
            @Override
            public Integer apply(Integer integer) {
                return integer+3;
            }
        }).limit(3).forEach(System.out::println);*/
        Stream.iterate(1,i -> i+3).limit(3).forEach(System.out::println);
        // 方式5:无限连续的无序流 与limit搭配使用
        /*Stream.generate(new Supplier<Integer>() {
            @Override
            public Integer get() {
                return (int)(Math.random()*10+1);
            }
        }).limit(5).forEach(System.out::println);*/
        Stream.generate(()->(int)(Math.random()*10+1)).limit(3).forEach(System.out::println);
    }
}

三 Stream常用API

1 筛选与切片

public class PlayTest {
    // 筛选与切片
    @Test
    public void playFilter(){
        // 对集合中的元素进行过滤
        List<Integer> list= Arrays.asList(-2,4,0,4,12,85);
        list.stream()
                //显示所有偶数  -2 4 0 4 12
                .filter(i->i%2==0)
                // 去除重复元素 -2 4 0 12
                .distinct()
                // 保留指定个数 -2 4 0
                .limit(3)
                // 跳过几个元素 4 0
                .skip(1)
                .forEach(System.out::print);
    }
}

2 映射

public class PlayTest {
    @Test
    public void playMap(){
        // 字符串转小写
        List<String> s=Arrays.asList("daw","swfgeWEFA","AG");
        /*s.stream().map(new Function<String, String>() {
            @Override
            public String apply(String s) {
                return s.toLowerCase();
            }
        }).forEach(System.out::println);*/
        // s.stream().map(s1->s1.toLowerCase()).forEach(System.out::println);
        s.stream().map(String::toLowerCase).forEach(System.out::println);
    }
    @Test
    public void playFlatMap(){
        // 两集合做一个Stream对象(取并集)  stream.of
        List<Integer> l1=Arrays.asList(1,2,3);
        List<Integer> l2=Arrays.asList(3,4,5);
        /*Stream.of(l1,l2).flatMap(new Function<List<Integer>, Stream<?>>() {
            @Override
            public Stream<?> apply(List<Integer> integers) {
                return integers.stream();
            }
        }).forEach(System.out::println);
        Stream.of(l1,l2).flatMap(i->i.stream()).forEach(System.out::println);*/
        Stream.of(l1,l2).flatMap(List::stream).forEach(System.out::println);
    }
}

3 排序

public class PlayTest {
    @Test
    public void playSort(){
        // 对集合中的元素排序  默认升序  泛型为数值
        List<Integer> list= Arrays.asList(-2,4,0,4,12,85);
        // 升序
        list.stream().sorted().forEach(System.out::println);
        // 降序
        list.stream().sorted(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        }).forEach(System.out::println);
        list.stream().sorted(Comparator.reverseOrder()).forEach(System.out::println);
    }
}

4 查找匹配

public class PlayTest {
    @Test
    public void playMatch(){
        List<Integer> list= Arrays.asList(-2,4,0,4,12,85);
        // 查询是否所有元素都大于0
        boolean f1=list.stream().allMatch(i->i>0);
        System.out.println(f1);
        // 查询是否有个别元素小于0
        boolean f2=list.stream().anyMatch(i->i<0);
        System.out.println(f2);
        // 查询是否真的没有匹配到0
        boolean f3=list.stream().noneMatch(i->i==0);
        System.out.println(f3);
        // 返回集合中第一个元素
        Optional<Integer> f4=list.stream().findFirst();
        if(f4.isPresent()){
            System.out.println(f4.get());
        }
        // 返回集合中热任一元素
        Optional<Integer> any = list.stream().findAny();
        if(any.isPresent()){
            System.out.println(any.get());
        }
    }
}

5 统计

public class PlayTest {
	@Test
    public void playCount(){
        List<Integer> list= Arrays.asList(-2,4,0,4,12,85);
        // 集合数据的元素总个数
        long count = list.stream().count();
        System.out.println(count);
        // 查询集合元素的最大值
        Optional<Integer> max=list.stream().max(Comparator.comparingInt(i->i));
        if(max.isPresent()){
            System.out.println(max.get());
        }
        // 查询有最小值
        Optional<Integer> min=list.stream().min(Comparator.comparingInt(i->i));
        if(min.isPresent()){
            System.out.println(min.get());
        }
    }
}

6 汇总

public class PlayTest {
	@Test
    public void playCollect(){
        // Stream转集合
        // 转list
        List<Object> l1=Stream.of(5,456,-5,3.14).collect(Collectors.toList());
        System.out.println(l1);
        // 转set
        List<Integer> l2=Arrays.asList(-2,4,0,4,12,85);
        Set<Integer> set = l2.stream().collect(Collectors.toSet());
        System.out.println(set);
        // 转TreeSet
        TreeSet<Integer> treeSet = l2.stream().collect(Collectors.toCollection(TreeSet::new));
        System.out.println(treeSet);
        // 转map 目前Stream是单列 map为双列 故转为map后key同时也是value
        // key不能重复 转换前先去重 两种方式去重 转set集合 或用Stream中的distinct()方法
/*        Map<Integer,Integer> map=l2.stream().distinct()
                .collect(Collectors.toMap(new Function<Integer, Integer>() {
                    @Override
                    public Integer apply(Integer key) {
                        return key;
                    }
                }, new Function<Integer, Integer>() {
                    @Override
                    public Integer apply(Integer value) {
                        return value;
                    }
                }));*/
        Map<Integer,Integer> map=l2.stream().distinct()
                .collect(Collectors.toMap(k->k,v->v));
        System.out.println(map);
        // 求和 平均值 最大 最小
        Integer sum=l2.stream().collect(Collectors.summingInt(i->i));
        System.out.println(sum);
        Double avg=l2.stream().collect(Collectors.averagingDouble(i->i));
        System.out.println(avg);
        Optional<Integer> max=l2.stream()
                .collect(Collectors.maxBy(Comparator.comparingInt(i->i)));
        if(max.isPresent()){
            System.out.println(max.get());
        }
        Optional<Integer> min=l2.stream()
                .collect(Collectors.minBy(Comparator.comparingInt(i->i)));
        if(min.isPresent()){
            System.out.println(min.get());
        }
    }
}

7 Optional容器

  作用:防止集合中元素没有获取到从而出现空指向异常
  原理:通过制定方法获取集合中指定的元素,存放到optional容器中,此容器只能存放1个或0个元素,因此只需对容器判断即可

List<String> list=new ArrayList<>();
        /*String s=list.stream().findFirst(); // null
        System.out.println(s.length());  //NullpointException*/
        Optional<String> f=list.stream().findFirst();
        if(f.isPresent()){
            String s=f.get();
        }

四 分区和分组

1 作用

  分组:根据指定条件进行组别的划分

  分区:根据指定条件,只能将数据分为两个区域(一个是满足条件(true));一个是不满足条件(false)区域

2 例子

实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
    private String name;
    private Integer age;
    private Long id;
    private Integer kg;
}

测试类

public class EmployeeStreamTest {
    private static List<Employee> employees=new ArrayList<>();
    static {
        employees.add(new Employee("大黄",4,0301L,20));
        employees.add(new Employee("大白",4,0302L,18));
        employees.add(new Employee("小黑",2,0303L,12));
    }
    // 根据年龄分组
    @Test
    public void playGroup(){
        /*Map<Integer,List<Employee>> map=employees.stream()
                .collect(Collectors.groupingBy(new Function<Employee, Integer>() {
                    @Override
                    public Integer apply(Employee employee) {
                        return employee.getAge();
                    }
                }));*/
        Map<Integer,List<Employee>> map=employees.stream()
                .collect(Collectors.groupingBy(Employee::getAge));
        System.out.println(map);
        // {2=[Employee(name=小黑, age=2, id=195, kg=12)],
        // 4=[Employee(name=大黄, age=4, id=193, kg=20),
        // Employee(name=大白, age=4, id=194, kg=18)]}
    }
    // 通过体重进行分区 true>=18 false<18
    @Test
    public void playPart(){
        /*Map<Boolean,List<Employee>> map=employees.stream()
                .collect(Collectors.partitioningBy(new Predicate<Employee>() {
                    @Override
                    public boolean test(Employee employee) {
                        return employee.getKg()>=18;
                    }
                }));*/
        Map<Boolean,List<Employee>> map=employees.stream()
                .collect(Collectors.partitioningBy(p->p.getKg()>=18));
        System.out.println(map);
        // {false=[Employee(name=小黑, age=2, id=195, kg=12)],
        // true=[Employee(name=大黄, age=4, id=193, kg=20),
        // Employee(name=大白, age=4, id=194, kg=18)]}
        System.out.println(map.get(true));//体重不小于18kg的
        System.out.println(map.get(false));//体重小于18kg的
    }
}

五 并行和并发

1 并发

  单核操作,按照指定的顺序完成操作,适用于处理数据量较小的操作,效率高 --stream()

2 并行

  必须是多核操作,随机执行,适用于处理数据量较大的操作 – parallelStream

3 例子

public class PlayTest {
    @Test
    public void play(){
        List<String> list= Arrays.asList("大黄","大白","小黑");
        // 并发
        list.stream().forEach(System.out::println);
        // 并行
        list.parallelStream().forEach(System.out::println);
        // 并发转并行
        list.stream().parallel().forEach(System.out::println);
    }
}
  • 17
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泰勒疯狂展开

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值