JDK8新特性--Stream流

1.为什么使用Stream流

当我们需要对集合中的元素进行操作的时候,除了必需的添加、删除、获取外,最典型的就是集合遍历。我们来体验 集合操作数据的弊端,需求如下:

一个ArrayList集合中存储有以下数据:张无忌,周芷若,赵敏,张强,张三丰
需求:1.拿到所有姓张的 2.拿到名字长度为3个字的 3.打印这些数据

public class My {
    public static void main(String[] args) {
// 一个ArrayList集合中存储有以下数据:张无忌,周芷若,赵敏,张强,张三丰
// 需求:1.拿到所有姓张的 2.拿到名字长度为3个字的 3.打印这些数据
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
// 1.拿到所有姓张的
        ArrayList<String> zhangList = new ArrayList<>(); // {"张无忌", "张强", "张三丰"}
        for (String name : list) {
            if (name.startsWith("张")) {
                zhangList.add(name);
            }
        }
// 2.拿到名字长度为3个字的
        ArrayList<String> threeList = new ArrayList<>(); // {"张无忌", "张三丰"}
        for (String name : zhangList) {
            if (name.length() == 3) {
                threeList.add(name);
            }
        }
// 3.打印这些数据
        for (String name : threeList) {
            System.out.println(name);
        }
    }
}

分析:

这段代码中含有三个循环,每一个作用不同:

  1. 首先筛选所有姓张的人;

  2. 然后筛选名字有三个字的人;

  3. 最后进行对结果进行打印输出。

每当我们需要对集合中的元素进行操作的时候,总是需要进行循环、循环、再循环。这是理所当然的么?不是。循环 是做事情的方式,而不是目的。每个需求都要循环一次,还要搞一个新集合来装数据,如果希望再次遍历,只能再使 用另一个循环从头开始。

那Stream能给我们带来怎样更加优雅的写法呢?

Stream的更优写法

public class Test {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰","何线程");
        list.stream()
                .filter(item->item.startsWith("张"))
                .filter(item->item.length()==3)
                .forEach(item-> System.out.println(item));
    }
}

 对集合的操作语法简洁:性能比传统快。

2.Stream流的原理

注意:Stream和IO流(InputStream/OutputStream)没有任何关系,请暂时忘记对传统IO流的固有印象!

Stream流式思想类似于工厂车间的“生产流水线”,Stream流不是一种数据结构,不保存数据,而是对数据进加工 处理。Stream可以看作是流水线上的一个工序。在流水线上,通过多个工序让一个原材料加工成一个商品。

3.如何获取Stream流

1.通过Collection对象的Stream()或parallelStream()方法

ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
        //通过集合对象来调用Stream串行流
        Stream<String> stream = list.stream();
        //通过集合对象来调用Stream并行流
        Stream<String> stringStream = list.parallelStream();

 2.通过Arrys类的Stream()方法

 //通过Arrays的Stream()方法来调用
        int[] arr = {1,2,1,3,4,5,6};
        IntStream stream1 = Arrays.stream(arr);

3.通过Stream接口的of(),iterate(),generate()方法

//通过Stream的of()来调用
        Stream<String> list1 = Stream.of("张无忌", "周芷若", "赵敏", "张强", "张三丰");

4.通过IntStream、LongStream、DoubleStream接口中的of,range,rangeClosed方法

     LongStream longStream = LongStream.of(1, 2, 3, 4, 5, 8, 6, 8);
        //通过LongStream.range 来获取 1-10 的Stream流对象但不包含10,
        LongStream range = LongStream.range(1, 10);
        //通过LongStream.rangeClosed 来g获取 1-10 的Stream流对象 包含10,
        LongStream longStream1 = LongStream.rangeClosed(1, 10);

4. Stream流中常见的api

中间操作api: 一个操作的中间链,对数据源的数据进行操作。而这种操作的返回类型还是一个Stream对象。

终止操作api: 一个终止操作,执行中间操作链,并产生结果,返回类型不在是Stream流对象。

 

 filter 筛选 / foreach 遍历 / count 计数

public class Test02 {
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("欧阳雪",18,"中国",'F'));
        personList.add(new Person("Tom",24,"美国",'M'));
        personList.add(new Person("Harley",22,"英国",'F'));
        personList.add(new Person("向天笑",20,"中国",'M'));
        personList.add(new Person("李康",22,"中国",'M'));
        personList.add(new Person("小梅",20,"中国",'F'));
        personList.add(new Person("何雪",21,"中国",'F'));
        personList.add(new Person("李康",22,"中国",'M'));
        //1.找出年龄大于18的人并输出;filter()过滤器需要一个断言接口函数
        //无论执行多少个中间操作 如果没有终止草错那么中间操作都不会被执行
        personList.stream().filter(item->item.getAge()>18).forEach(System.out::println);
        // 2.找出所有中国人的数量 count 计数终止操作
        long count = personList.stream().filter(item -> item.getCountry() == "中国").count();
        System.out.println(count);
    }
}
class Person {
    private String name;
    private Integer age;
    private String country;
    private char sex;

    public Person(String name, Integer age, String country, char sex) {
        this.name = name;
        this.age = age;
        this.country = country;
        this.sex = sex;
    }

    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 String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", country='" + country + '\'' +
                ", sex=" + sex +
                '}';
    }
}

map  | sorted 排序

map--接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

        //3.只要每个对象中的名字  map 原来流中的每一个元素转换成另一个格式
        personList.stream().map(item->item.getAge()).forEach(System.out::println);
        //4
        personList.stream().map(item->{
            Map map = new HashMap();
            map.put("name",item.getName());
            map.put("age",item.getAge());
            return map;
        }).forEach(System.out::println);
        //将流中的元素排序
        personList.stream().sorted((o1, o2) -> o1.getAge().compareTo(o2.getAge())).forEach(System.out::println);

 min 最小 / max  最大 /distinct 去重

  //6.查找年龄最大的人 max是终止操作
        Optional<Person> max = personList.stream().max((o1, o2) -> o1.getAge().compareTo(o2.getAge()));
        System.out.println("年龄最大的人"+max.get());
        //7.查找年龄最小的人
        Optional<Person> min = personList.stream().min((o1, o2) -> o1.getAge().compareTo(o2.getAge()));
        System.out.println("年龄最小的人"+min.get());
        // 查看都有那个国家的人
        personList.stream().map(item->item.getCountry()).distinct().forEach(System.out::println);

reduce/规约

        //8.求集合中所有人的年龄和
        //reduce 规约把一流缩减成一个值,能实现对集合就和,求乘积和求最值的操作   reduce(a, b)可以不写 10  10代表这a的初始值为10
        Optional<Integer> reduce = personList.stream().map(item -> item.getAge()).reduce((a, b) -> a + b);
        System.out.println(reduce.get());

 collect /搜集 match find

 //collect 收集方法
        //9 年龄大于20的且性别为男
        List<Person> collect = personList.stream()
                .filter(item -> item.getAge() > 20)
                .filter(item -> item.getSex() == 'M')
                .collect(Collectors.toList());
        System.out.println(collect);
        //find匹配  match查找
        Optional<Person> first = personList.stream().findFirst();
        System.out.println(first);
        // findFirst 获取第一个 findand 随机获取一个
        Optional<Person> any = personList.stream().parallel().findAny();
        // match 所有元素满足条件返回true 否则返回true  anyMatch 只要有一个元素满足条件就返回true noneMatch 没有满足条件的返回true
        boolean b = personList.stream().parallel().allMatch(item -> item.getAge() > 20);
        boolean c = personList.stream().parallel().anyMatch(item -> item.getAge() > 20);
        System.out.println(b);
        System.out.println(c);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值