JDK8之lambda表达式

Wesley13
• 阅读 592
/**
 *JDK8  Stream特性
 * Created by chengbx on 2018/5/27.
 * Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、
 * 高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。
 * Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。
 * 同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,
 * 使用 fork/join 并行方式来拆分任务和加速处理过程。
 * 通常编写并行代码很难而且容易出错,但使用 Stream API 无需编写一行多线程的代码,
 * 就可以很方便地写出高性能的并发程序。
 * 所以说,Java 8 中首次出现的 java.util.stream 是一个函数式语言+多核时代综合影响的产物。
 *  一、Stream API 的操作步骤:
 *        
 * 1. 创建 Stream
 *
 * 2. 中间操作
 *
 * 3. 终止操作(终端操作)
 *
 * 4.   接口中的默认方法
 *      接口默认方法的”类优先”原则
 *      若一个接口中定义了一个默认方法,而另外一个父类或接口中
 *      又定义了一个同名的方法时
 *      1.选择父类中的方法。如果一个父类提供了具体的实现,那么
 *      接口中具有相同名称和参数的默认方法会被忽略.
 *      2.接口冲突。如果一个父接口提供一个默认方法,而另一个接
 *      口也提供了一个具有相同名称和参数列表的方法(不管方法
 *      是否是默认方法),那么必须覆盖该方法来解决冲突
 * 5.   新增的重复注解@Repeatble和类型注解
 *         java8新增了重复注解,其使用方式为:
             @Repeatable(Authorities.class)
             public @interface Authority {
                String role();
             }
             public @interface Authorities {
                Authority[] value();
             }
             public class RepeatAnnotationUseNewVersion {
                 @Authority(role="Admin")
                 @Authority(role="Manager")
                 publicvoiddoSomeThing(){ }
             }
      2.Java8为ElementType枚举增加了TYPE_PARAMETER、TYPE_USE两个枚举值,
             从而可以使用@Target(ElementType_TYPE_USE)修饰注解定义,这种注解被称为类型注解,
             可以用在任何使用到类型的地方
 */
public class TestStream {

    List<Employee> employees = Arrays.asList(
            new Employee("aaa",11,5000),
            new Employee("bbb",21,5200),
            new Employee("ccc",13,5500),
            new Employee("ddd",54,6400),
            new Employee("eee",16,7100),
            new Employee("fff",74,7120),
            new Employee("ggg",12,7150)
    );
    /**
     * 创建stream
     */
    @Test
    public void test1(){
        //1. Collection 提供了两个方法  stream() 与 parallelStream()
        List<String> list = new ArrayList<>();
        Stream<String> stream =  list.stream();
        Stream<String> parallelStream = list.parallelStream(); //获取一个并行流
        //2. 通过 Arrays 中的 stream() 获取一个数组流
        Integer[] nums = new Integer[10];
        Stream<Integer> stream1 = Arrays.stream(nums);
        //3. 通过 Stream 类中静态方法 of()
        Stream<Integer> stream2 = Stream.of(1,2,3,4,5,6);
        //4. 创建无限流
        //迭代
        Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 2).limit(10);
        stream3.forEach(System.out::println);

        //生成
        Stream<Double> stream4 = Stream.generate(Math::random).limit(2);
        stream4.forEach(System.out::println);
    }
    /*
      筛选与切片
        filter——接收 Lambda , 从流中排除某些元素。
        limit——截断流,使其元素不超过给定数量。
        skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,
        则返回一个空流。与 limit(n) 互补
        distinct——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
     */
    //内部迭代:迭代操作 Stream API 内部完成
    @Test
    public void test2(){
        //中间操作,不会执行任何操作
        Stream<Employee> str = employees.stream().filter((e) -> e.getAge()>30).limit(1);
        //终止操作,一次性执行全部内容,即"惰性求值"
        str.forEach(System.out::println);
        // employees.stream().filter((e) -> e.getAge()<30)
        //            .forEach((employee) -> System.out.println(employee));
    }
    //外部迭代
    @Test
    public void test3(){
        Iterator<Employee> it = employees.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
    @Test
    public void test4(){
        employees.stream()
                .filter((e) -> {
                    System.out.println("短路!"); // &&  ||
                    return e.getSalary() >= 5000;
                }).limit(3)
                .forEach(System.out::println);
    }

    @Test
    public void test5(){
        employees.parallelStream()
                .filter((e) -> e.getSalary() >= 5000)
                .skip(2)
                .forEach(System.out::println);
    }
    @Test
    public void test6(){
        employees.stream()
                .distinct()
                .forEach(System.out::println);
    }

    /**
     * 映射
     * map -接收lambda,将元素转换成其他形式获取信息,接收一个函数作为参数,
            该函数会被应用在每个元素上,并将其映射成一个新的元素。
     * flatmap-接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
     */
    @Test
    public void test7(){
        List<String> list = Arrays.asList("aaa","bbb","ccc","ddd");
        list.stream().map((str) -> str.toUpperCase())
                     .forEach((str) -> System.out.println(str));
        System.out.println("---------------");
        employees.stream().map(Employee::getName)
                 .forEach((name) ->System.out.println(name));
    }
    /**
     * 排序
     * sorted()--自然排序(comparable)
     * sorted(Comparator com)--定制排序(Comparator)
     */
    @Test
    public void test8(){
        List<String> list = Arrays.asList("eee","ggg","ccc","ddd");
        list.stream().sorted().forEach(System.out::println);
        System.out.println("-------------------以下是定制排序-------------");
        employees.stream().sorted((e1,e2) ->{
            if (e1.getAge() ==e2.getAge()) {
                return e1.getName().compareTo(e2.getName());
            }else{
                return Integer.compare(e1.getAge(),e2.getAge());
            }
        }).forEach((employee) -> System.out.println(employee));
    }
    //3. 终止操作
    /*
        allMatch——检查是否匹配所有元素
        anyMatch——检查是否至少匹配一个元素
        noneMatch——检查是否没有匹配的元素
        findFirst——返回第一个元素
        findAny——返回当前流中的任意元素
        count——返回流中元素的总个数
        max——返回流中最大值
        min——返回流中最小值
        注意:流进行了终止操作后,不能再次使用
     */

    @Test
    public void test9(){
        boolean b = employees.stream().allMatch((emp) -> emp.getAge()==15);
        System.out.println(b);
        System.out.println("---------------");
        boolean b1 = employees.stream().anyMatch((emp) -> emp.getAge()==15);
        System.out.println(b1);
        System.out.println("---------------");
        boolean b2 = employees.stream().noneMatch((emp) -> emp.getAge()==15);
        System.out.println(b2);
        System.out.println("---------------");
        Optional<Employee> optional = employees.stream()
                .sorted((emp1, emp2) -> Double.compare(emp1.getSalary(),emp2.getSalary()))
                .findFirst();
        System.out.println(optional.get());
        System.out.println("---------------");
        Optional<Employee> optional1 = employees.parallelStream()
                                                .filter((emp) -> emp.getAge() >15).findAny();
        System.out.println(optional1);
        System.out.println("---------------");
        Long count = employees.parallelStream().filter((emp) -> emp.getAge() >15).count();
        System.out.println(count);
        Optional<Double> optiona3 = employees.stream()
                                             .map((emp) -> emp.getSalary()).max(Double::compareTo);
        System.out.println(optiona3.get());
        System.out.println("---------------");
        Optional<Employee> optiona4 = employees.stream()
                                               .min((e1,e2) ->Double.compare(e1.getSalary(),e2.getSalary()));
        System.out.println(optiona4);
    }

    /**
     * 归约
     reduce(T identity, BinaryOperator) / reduce(BinaryOperator) ——可以将流中元素反复结合起来,得到一个值。
     */
    @Test
    public void test10(){
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        Integer sum = list.stream().reduce(0,(x,y) -> x+y);
        System.out.println(sum);//55
        System.out.println("---------------------");
        Optional<Double> sumSal = employees.stream().map(Employee::getSalary).reduce(Double::sum);
        System.out.println(sumSal);
    }
    /**
     * 收集:
     * collect——将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
     */
    //将employee集合中name值取出来放入集合中 aaa bbb ccc ddd eee fff ggg
    @Test
    public void test11(){
        List list = employees.stream().map(Employee::getName).collect(Collectors.toList());
        list.forEach(System.out::println);
    }
    @Test
    public void test12(){
        Set set = employees.stream().map(Employee::getName).collect(Collectors.toSet());
        set.forEach(System.out::println);
    }
    @Test
    public void test13(){
        HashSet hashSet = employees.stream().map(Employee::getName)
                                   .collect(Collectors.toCollection(HashSet::new));
        hashSet.forEach(System.out::println);
    }
    //获取集合中元素的个数  7
    @Test
    public void test14(){
        long count =  employees.stream().collect(Collectors.counting());
        System.out.println(count);
        System.out.println("----------------");
        //获取工资平均值
        Double avgMoney = employees.stream()
                                   .collect(Collectors.averagingDouble((emp) -> emp.getSalary()));
        System.out.println(avgMoney);//6210.0
        System.out.println("----------------");
        //工资总和
        Double sumMoney = employees.stream()
                                   .collect(Collectors.summingDouble(Employee::getSalary));
        System.out.println(sumMoney);
        //最大值
        Optional<Employee> optional= employees.stream()
                .collect(Collectors.maxBy((emp1,emp2) -> Double.compare(emp1.getSalary(),emp2.getSalary())));
        System.out.println(optional.get());//Employee{name='ggg', age=12, salary=7150.0}
        //最小值
        Optional<Double> minMoney = employees.stream()
                        .map(Employee::getSalary).collect(Collectors.minBy(Double::compare));
        System.out.println(minMoney.get());
    }
    //分组
    @Test
    public void test15(){
                employees.stream()
                .collect(Collectors.groupingBy(Employee::getAge));
    }
    //分区
    @Test
    public  void test16(){
       Map<Boolean,List<Employee>> map =employees.stream()
                                        .collect(Collectors.partitioningBy((e) -> e.getSalary() >6000));
        System.out.println(map);
        //{false=[Employee{name='aaa', age=11, salary=5000.0}, Employee{name='bbb', age=21, salary=5200.0},
        // Employee{name='ccc', age=13, salary=5500.0}],
        // true=[Employee{name='ddd', age=54, salary=6400.0}, Employee{name='eee', age=16, salary=7100.0},
        // Employee{name='fff', age=74, salary=7120.0}, Employee{name='ggg', age=12, salary=7150.0}]}

    }

    @Test
    public void test17(){
        DoubleSummaryStatistics dss =employees.stream()
                                              .collect(Collectors.summarizingDouble(Employee::getSalary));
        //求平均值
        System.out.println(dss.getAverage());
        //求最大值
        System.out.println(dss.getMax());
        //求和
        System.out.println(dss.getSum());
    }    @Test
    public void test18(){
        String name = employees.stream().map(Employee::getName).collect(Collectors.joining(","));
        System.out.println(name);//aaa,bbb,ccc,ddd,eee,fff,ggg
    }
}
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
Java8 新特性之集合操作Stream
Java8新特性之集合操作StreamStream简介Java8引入了全新的StreamAPI。这里的Stream和I/O流不同,它更像具有Iterable的集合类,但行为和集合类又有所不同。stream是对集合对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作,或者大批量数据操作。
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这