Java中的Stream API使用

Stream是一种可供流式操作的数据视图,有些类似数据库中的视图,不改变源数据集合,如果进行改变的操作会返回新的数据集合。

总的来讲它有三大特性:1、stream不存储数据 ; 2、stream不改变源数据 ; 3、stream的延迟执行特性

Stream API常用方法

中间操作

(Intermediate operations)

无状态(Stateless)unordered()   filter()   map()   mapToInt()   mapToLong()   mapToDouble()   flatMap() flatMapToInt()   flatMapToLong()   flatMapToDouble()   peek()
有状态(Stateful)distinct()   sorted()   limit()   skip()

结束操作

(Terminal

operations)

非短路操作forEach()   forEachOrdered()   toArray()   reduce()   collect()   max()   min()   count()

短路操作

(short-circuiting)

anyMatch()   allMatch()   noneMatch()   findFirst()   findAny()
常用中间件结束操作

filter:过滤流,过滤流中的元素,返回一个符合条件的Stream

map:转换流,将一种类型的流转换为另外一种流。(mapToInt、mapToLong、mapToDouble 返回int、long、double基本类型对应的Stream)

 flatMap:简单的说,就是一个或多个流合并成一个新流。(flatMapToInt、flatMapToLong、flatMapToDouble 返回对应的IntStream、LongStream、DoubleStream流。)

peek:主要用来查看流中元素的数据状态。

 

distinct:返回去重的Stream。

sorted:返回一个排序的Stream。

limit:返回前n个元素数据组成的Stream。属于短路操作

skip:返回第n个元素后面数据组成的Stream。 

forEach: 循环操作Stream中数据。

toArray: 返回流中元素对应的数组对象。

reduce: 聚合操作,用来做统计。

collect: 聚合操作,封装目标数据。

min、max、count: 聚合操作,最小值,最大值,总数量。

forEachOrdered: 暗元素顺序执行循环操作。

 

anyMatch: 短路操作,有一个符合条件返回true。

allMatch: 所有数据都符合条件返回true。

noneMatch: 所有数据都不符合条件返回true。

findFirst: 短路操作,获取第一个元素。

findAny: 短路操作,获取任一元素。

所有操作分为两类:中间操作和结束操作,中间操作只是一种标记,只有结束操作才会触发实际计算

中间操作:(1)无状态中间操作是指元素的处理不受前面元素的影响;(2)有状态的中间操作必须等到所有元素处理之后才知道最终结果,比如排序是有状态操作,在读取所有元素之前并不能确定排序结果。

结束操作:(1)短路操作是指不用处理全部元素就可以返回结果,比如找到第一个满足条件的元素。

之所以要进行如此精细的划分,是因为底层对每一种情况的处理方式不同。

Stream简介

Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的 Iterator。原始版本的 Iterator,用户只能显式地一个一个遍历元素并对其执行某些操作;高级版本的 Stream,用户只要给出需要对其包含的元素执行什么操作,比如 “过滤掉长度大于 10 的字符串”、“获取每个字符串的首字母”等,Stream 会隐式地在内部进行遍历,做出相应的数据转换。
Stream 就如同一个迭代器(Iterator),单向,不可往复,数据只能遍历一次,遍历过一次后即用尽了,就好比流水从面前流过,一去不复返。
而和迭代器又不同的是,Stream 可以并行化操作,迭代器只能命令式地、串行化操作。顾名思义,当使用串行方式去遍历时,每个 item 读完后再读下一个 item。而使用并行去遍历时,数据会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出。Stream 的并行操作依赖于 Java7 中引入的 Fork/Join 框架(JSR166y)来拆分任务和加速处理过程。

Stream和Collection的区别主要有:
1.stream本身并不存储数据,数据是存储在对应的collection里,或者在需要的时候才生成的;
2.stream不会修改数据源,总是返回新的stream;
3.stream的操作是懒执行(lazy)的:仅当最终的结果需要的时候才会执行

Stream的生成方式

1)从Collection和数组获得

  • Collection.stream()
  • Collection.parallelStream()  (并行执行的流.它通过默认的ForkJoinPool,可能提高多线程任务的速度)
  • Arrays.stream(T array) or Stream.of()

(2)从BufferedReader获得

  • java.io.BufferedReader.lines()

(3)静态工厂

  • java.util.stream.IntStream.range()
  • java.nio.file.Files.walk()

(4)自己构建

  • java.util.Spliterator

(5)其他

  • Random.ints()
  • BitSet.stream()
  • Pattern.splitAsStream(java.lang.CharSequence)
  • JarFile.stream()

案例说明

public class Person {  // 举例实体类
  
    private Integer  id;
    
    private String name;
    
    private String sex;
    
    private Integer age;
    
    //get,set方法和满参构造函数忽略
}

1、map相关

public class TestMap {

    public static void main(String[] args) {
        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person(1,"张三","男",38));
        personList.add(new Person(2,"小小","女",2));
        personList.add(new Person(3,"李四","男",65));
        personList.add(new Person(4,"王五","女",20));
        personList.add(new Person(5,"赵六","男",38));
        personList.add(new Person(6,"大大","男",65));

        //1、只取出该集合中所有姓名组成一个新集合
        List<String> nameList=personList.stream().map(Person::getName).collect(Collectors.toList());
        System.out.println(nameList.toString());

        //2、只取出该集合中所有id组成一个新集合
        List<Integer> idList=personList.stream().mapToInt(Person::getId).boxed().collect(Collectors.toList());
        System.out.println(idList.toString());

        //3、list转map,key值为id,value为Person对象
        Map<Integer, Person> personmap = personList.stream().collect(Collectors.toMap(Person::getId, person -> person));
        System.out.println(personmap.toString());

        //4、list转map,key值为id,value为name
        Map<Integer, String> namemap = personList.stream().collect(Collectors.toMap(Person::getId, Person::getName));
        System.out.println(namemap.toString());

        //5、进行map集合存放,key为age值 value为Person对象 它会把相同age的对象放到一个集合中
        Map<Integer, List<Person>> ageMap = personList.stream().collect(Collectors.groupingBy(Person::getAge));
        System.out.println(ageMap.toString());

        //6、获取最小年龄
        Integer ageMin = personList.stream().mapToInt(Person::getAge).min().getAsInt();
        System.out.println("最小年龄为: "+ageMin);

        //7、获取最大年龄
        Integer ageMax = personList.stream().mapToInt(Person::getAge).max().getAsInt();
        System.out.println("最大年龄为: "+ageMax);

        //8、集合年龄属性求和
        Integer ageAmount = personList.stream().mapToInt(Person::getAge).sum();
        System.out.println("年龄总和为: "+ageAmount);
    }
}

这里要注意,如果list转map的key不唯一,结果会报错,如果不确定你的key是否唯一,可以做如下修改:

public static void main(String[] args) {
        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person(1, "张三", "男", 38));
        personList.add(new Person(2, "小小", "女", 2));
        personList.add(new Person(3, "李四", "男", 65));
        personList.add(new Person(4, "王五", "女", 20));
        personList.add(new Person(5, "赵六", "男", 38));
        personList.add(new Person(6, "大大", "男", 65));

        //list转map,key值为age,value为Person对象
        // 1.错误情况
        Map<Integer, Person> error = personList.stream().collect(Collectors.toMap(Person::getAge, person -> person));

        // 修改情况(以第一次插入的value为主)
        Map<Integer, Person> chang1 = personList.stream().collect(Collectors.toMap(Person::getAge, person -> person,
                (key1, key2) -> key1));
        System.out.println(chang1.toString());
        // 修改情况(以最后一次插入的value为主)
        Map<Integer, Person> chang2 = personList.stream().collect(Collectors.toMap(Person::getAge, person -> person,
                (key1, key2) -> key2));
        System.out.println(chang2.toString());
    }

2、filter相关

public class TestFilter {

    public static void main(String[] args) {
        List<Person> persionList = new ArrayList<Person>();
        persionList.add(new Person(1, "张三", "男", 8));
        persionList.add(new Person(2, "小小", "女", 2));
        persionList.add(new Person(3, "李四", "男", 25));
        persionList.add(new Person(4, "王五", "女", 8));
        persionList.add(new Person(5, "赵六", "女", 25));
        persionList.add(new Person(6, "大大", "男", 65));

        //1、查找年龄大于20岁的人数
        long  age=persionList.stream().filter(p->p.getAge()>20).count();
        System.out.println(age);

        //2、查找年龄大于20岁,性别为男的人数
       List<Person>  ageList=persionList.stream().filter(p->p.getAge()>20).filter(p->"男".equals(p.getSex())).collect(Collectors.toList());
       System.out.println(ageList.size());
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值