java代码之美(2)---Java8 Stream

Stream

第一次看到Stream表达式就深深把我吸引,用它可使你的代码更加整洁并且对集合的操做效率也会大大提升,若是你尚未用到java8的Stream特性,那就说明你确实out啦。html

1、概述

一、什么是Stream

Stream是一种可供流式操做的数据视图有些相似数据库中视图的概念它不改变源数据集合若是对其进行改变的操做它会返回一个新的数据集合。java

总的来说它有三大特性:在以后咱们会对照着详细说明数据库

       一、stream不存储数据编程

       二、stream不改变源数据数组

       三、stream的延迟执行特性less

二、Stream优势

  1. 代码简洁,函数式编程写出的代码简洁且意图明确,使用stream接口让你今后告别for循环。函数式编程

  2. 多核友好,Java函数式编程使得编写并行程序从未如此简单,你须要的所有就是调用一下parallel()方法。函数

三、Stream API经常使用方法

Stream操做分类
中间操做(Intermediate operations) 无状态(Stateless) unordered() filter() map() mapToInt() mapToLong() mapToDouble() flatMap() flatMapToInt() flatMapToLong() flatMapToDouble() peek()
有状态(Stateful) distinct() sorted() sorted() limit() skip()
结束操做(Terminal operations) 非短路操做 forEach() forEachOrdered() toArray() reduce() collect() max() min() count()
短路操做(short-circuiting) anyMatch() allMatch() noneMatch() findFirst() findAny()

 

 

 

 

 

 

 

 

 

 

 

 

Stream上的全部操做分为两类:中间操做结束操做,中间操做只是一种标记,只有结束操做才会触发实际计算。post

中间操做又能够分为无状态的和有状态的:ui

      无状态中间操做是指元素的处理不受前面元素的影响,而有状态的中间操做必须等到全部元素处理以后才知道最终结果,好比排序是有状态操做,在读取全部元素以前并不能肯定排序结果;

结束操做又能够分为短路操做和非短路操做

      短路操做是指不用处理所有元素就能够返回结果,好比找到第一个知足条件的元素。之因此要进行如此精细的划分,是由于底层对每一种状况的处理方式不一样。

经常使用中间件

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

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

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

 distinct:返回去重的Stream。

  sorted:返回一个排序的Stream。

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

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

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

结束操做

  forEach: 循环操做Stream中数据。

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

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

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

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

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

    allMatch: 全部数据都符合条件返回true。

noneMatch: 全部数据都不符合条件返回true。

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

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

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

 

2、各类案例说明

多举点例子,之后忘记了还能够来找本身的博客,哈哈。

首先写一个领域对象

public class Person {
    
    private Integer  id;
    
    private String name;
    
    private String sex;
    
    private Integer age;
    
    //提供get,set,和满参构造函数
}

一、map中间件相关例子

 

public class TestMap {

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

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

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

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

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

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

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

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

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

 运行结果:

 

是否是以前要好几层的for循环解决的问题,经过Stream只要一行代码就能够解决了。

这里要注意,若是你list转map的key若是不惟一,会报错,因此若是你不肯定你的key是否惟一,能够改为以下:

 Map<Integer, String> map = persionList.stream().collect(
                Collectors.toMap(Person::getAge, Person::getName, (key1, key2) -> key1)
        );

 二、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));

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

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

    }
    /*
     *运行结果:
     *  3
     *  2
     */
}

 三、sorted相关例子

   对于数组举例

public class TestSort {

    String[] arr1 = {"abc","a","bc","abcd"};

    /**
     * 按照字符长度排序
     */
    @Test
    public void testSorted1_(){
        Arrays.stream(arr1).sorted(Comparator.comparing(String::length)).forEach(System.out::println);
        //输出:a、bc、abc、abcd
    }

    /**
     * 倒序
     * reversed(),java8泛型推导的问题,因此若是comparing里面是非方法引用的lambda表达式就没办法直接使用reversed()
     * Comparator.reverseOrder():也是用于翻转顺序,用于比较对象(Stream里面的类型必须是可比较的)
     * Comparator. naturalOrder():返回一个天然排序比较器,用于比较对象(Stream里面的类型必须是可比较的)
     */
    @Test
    public void testSorted2_(){
        Arrays.stream(arr1).sorted(Comparator.comparing(String::length).reversed()).forEach(System.out::println);
        //输出:abcd、abc、bc、a
        Arrays.stream(arr1).sorted(Comparator.reverseOrder()).forEach(System.out::println);
        //输出:bc、abcd、abc、a
        Arrays.stream(arr1).sorted(Comparator.naturalOrder()).forEach(System.out::println);
        //输出:a、abc、abcd、bc
    }

    /**
     * 先按照首字母排序
     * 以后按照String的长度排序
     */
    @Test
    public void testSorted3_(){
        Arrays.stream(arr1).sorted(Comparator.comparing(this::com1).thenComparing(String::length)).forEach(System.out::println);
    }
//输出:a、abc、abcd、bc
public char com1(String x){ return x.charAt(0); } }

 对于集合举例

public class TestSort {

    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));

        //一、找到年龄最小的岁数
        Collections.sort(persionList, (x, y) -> x.getAge().compareTo(y.getAge()));
        Integer age = persionList.get(0).getAge();
        System.out.println("年龄最小的有:" + age);
        //输出:年龄最小的有:2

        //二、找到年龄最小的姓名
        String name = persionList.stream()
                .sorted(Comparator.comparingInt(x -> x.getAge()))
                .findFirst()
                .get().getName();
        System.out.println("年龄最小的姓名:" + name);
        //输出:年龄最小的姓名:小小
    }
}

 其它的就不具体写了。之后遇到特殊的再往里面补充。

 

参考

    一、跟上 Java 8 – Stream API 快速入门

   二、java8之stream

   三、[Java进阶篇][函数式编程][Java 8+ Stream API]

   四、深刻理解Java Stream流水线

 

想太多,作太少,中间的落差就是烦恼。想没有烦恼,要么别想,要么多作。中校【10】 

相关文章
相关标签/搜索