javaSE高级篇5 — java8新特性详解———更新完毕

时间:2022-09-07 11:40:00

java8新特性

在前面已经见过一些东西了,但是:挖得有坑儿

1、lambda表达式

  • lambda表达式是jdk1.8引入的全新语法特性
  • 它支持的是:只有单个抽象方法的函数式接口。什么意思?
    • 就是说:这个接口下面只有一个抽象方法是真正属于自己的( 像那种从Object类里面继承过来的不算 ———— 所以这样严格来讲:这个接口里面就只有一个抽象方法是真正属于自己的 )
  • 什么时候会用这个东西? ———— 总的一句话是:传参的时候是一个函数式接口就会用( 这句话包含了很多东西,这里不理解没事儿,学完了就懂了 )
    • 1、简化匿名内部类 ( 学完这个lambda表达式之后,回过来采用 1、接口 ——> 实现类( new实现类对象,调接口中的方法 )、2、把接口的实现类弄成内部类( 成员、局部、匿名 )、3、弄成lambda表达式的样子,这样一步一步简化,推导出lambd表达式,最后一对比就突然发现lambda表达式好简单了( 注意:接口中那个抽象方法是单个参数、多个参数( lambda加不加()小括号 )、无返回值、有返回值( lambda写不写返回值类型 )、业务代码为一句、多句( lambda要不要加花括号{} 的情况 ) ) ———— 这句话很重要,记住这句话,然后弄完我后面说的这些之后,再回过来实践一下我说的这句话,会收获很多,只要把这句话搞懂了,lambda表达式就彻底懂了
      • 以前玩儿匿名内部类的时候不是弄过一点吗,回顾一下
        • package cn.xieGongZi.reviewInnerClass;
          
          import java.util.TreeSet;
          
          // 回顾一下以前玩匿名内部类
          public class Demo { public static void main(String[] args) { // 以前在treeSet中研究过它的底层排序原理,所以再来玩儿一下
          TreeSet<Integer> treeSet = new TreeSet<>(); treeSet.add(20);
          treeSet.add(30);
          treeSet.add(1);
          treeSet.add(9);
          treeSet.add(10);
          treeSet.add(18); System.out.println( treeSet ); // 这是升序排列,那我想降序排列呢? }
          }

          javaSE高级篇5  —  java8新特性详解———更新完毕

           来嘛:改变排序规则

        • package cn.xieGongZi.reviewInnerClass;
          
          import java.util.Comparator;
          import java.util.TreeSet; // 回顾一下以前玩的匿名内部类
          public class Demo { public static void main( String[] args ) { // 来吧:改变排序规则 ———— 重写comparator接口( 匿名内部类 )
          TreeSet<Integer> treeSet = new TreeSet<>( new Comparator<Integer>() {
          @Override
          public int compare( Integer o1, Integer o2 ) {
          // 注意观察这里 ( 这就是传递的参数、及参数个数 )
          // 记得用这个写法 和 lambda需要传参时的写法作对比
          return o2 - o1; // 改变比较规则
          }
          }); treeSet.add(20);
          treeSet.add(30);
          treeSet.add(1);
          treeSet.add(9);
          treeSet.add(10);
          treeSet.add(18); System.out.println( treeSet ); }
          }

          javaSE高级篇5  —  java8新特性详解———更新完毕

           这样虽然是把排序规则改变了,但是不麻烦吗?

          • 所以:lambda表达式来了————再来回顾一下lambda的表达式是怎么样的?
            • 【对象名】 ( 参数 )-> { 集合体( 业务代码 )}   ———— 那再来玩儿一下
              • package cn.xieGongZi.reviewInnerClass;
                
                import java.util.TreeSet;
                
                public class UseLambda {
                
                    public static void main(String[] args) {
                
                        // 来吧:改变排序规则 ———— 使用lambda表达式
                TreeSet<Integer> treeSet = new TreeSet<>( ( o1,o2 )-> {
                /*
                1、为什么这里写两个o1,o2的参数,然后加个{}
                这个表达式就可以去执行相应的东西
                即:这个表达式怎么知道:老衲重写的是Comparator接口?

                2、另外一个问题:看起来这个o1,o2貌似没有值吧
                它不是参数吗,在这里看起来没赋值啊,所以最后怎么可以得出想要的结果?
                */
                return o2 - o1;
                // 改变比较规则————即:业务代码
                } ); // 记得用这里的写法 和 前面匿名内部类那里的写法作对比 ———— 会发现lambda表达式如此的简单
                // 记得尝试模拟一个参数、多个参数、有返回值、无返回值的写法 ( 当然:不是用这个、而是自己设计 )
                treeSet.add(20);
                treeSet.add(30);
                treeSet.add(1);
                treeSet.add(9);
                treeSet.add(10);
                treeSet.add(18); System.out.println(treeSet);
                }
                }

                效果图如下:

                • javaSE高级篇5  —  java8新特性详解———更新完毕
              • 为了解决解决上述代码中的两个问题,来看一下如下代码( 顺便引申出函数式接口是什么意思 )
                • package cn.xieGongZi.functionInterface;
                  
                  public class Test {
                  
                      public static void main(String[] args) {
                  
                          // 开始玩儿
                  test test = new test();
                  test.doAdd( new TestFunctionInterface() {

                  /*
                  这中间的这一堆就是一个对象嘛 ———— 一个TestFunctionInterface对象
                  这里面是用了这个对象 去 调用了TestFunctionInterface中的add()方法
                  所以结果来了:lambda表达式中有一个对象名,这个对象名就是这里的TestFunctionInterface对象

                  传递的参数有没有值:有,为什么?
                  就是调用doAdd()方法的时候不得需要一个TestFunctionInterface对象吗,虽然使用lambda可以不用对象名
                  但是:参数是必写的 ( 因为add( int a ) 需要一个int类型的a ,如果add()没有参数就可以不写 )
                  然后这个对象就把这个参数a携带进去了,那这个对象把参数携带去了哪里?
                  把这个值赋给了重写的add( int a )方法里面需要的这个int a参数了嘛 因此:总结一句话就是lambda表达式就是指:
                  把一段代码( 如:t.add( int a ) —— 这里面可能需要携带参数,也可能不需要、甚至可能是一个、多个
                  需不需要携带参数,看那个接口中的抽象方法需不需要 )
                  传递给了某一个函数

                  最后让这个函数( 就是lambda做的事情 )去执行相关的操作( 这个操作是怎么样的,就是自己写的业务代码 )
                  要真正理解lambda表达式,关键就是这里的回调,就这里会绕一下
                  */

                  @Override
                  public void add( int a ) {
                  // 正常是这么玩儿的————重写这个方法
                  System.out.println("老衲自东土大唐而来....." + a );
                  }
                  }); /*
                  这里面doAdd()中是不是需要传一个TestFunctionInterface对象
                  这个对象指向的那个类型,就是他喵说的函数式接口( 这个接口只有一个真正属于自己的抽象方法 )

                  在java中是不是函数式接口,会有一个注解来进行说明@FunctionalInterface
                  这个就是一个声明性的东西而已
                  就相当于是给这个接口做了一个标记,标记它是一个函数式接口
                  */
                  }
                  } // 定义一个接口
                  interface TestFunctionInterface{ // 这里面只有这一个方法是真正属于这个接口的
                  void add( int a );
                  } class test{ public void doAdd( TestFunctionInterface t ){
                  /*
                  这个t就相当于是我们使用lambda时的那个对象名( 用lambda时可写可不写,看情况来做 )
                  */

                  t.add( int a ); // t.add()就相当于是lambda做的事情
                  // 这里用TestFunctionInterface对象t 回调了 TestFunctionInterface中的抽象方法

                  }
                  }
    • 再继续研究:函数式接口有哪些类型( 即:分为哪几种 )
      • 1、消费型( Consumer) ——— 又懵逼,这是啥子鬼玩意儿? ———— 看源码涩
        • javaSE高级篇5  —  java8新特性详解———更新完毕

           把源码提取出来分析一下

          • @FunctionalInterface
            public interface Consumer<T> { void accept(T t); // default Consumer<T> andThen(Consumer<? super T> after) { // 看不懂这里的话,那这一段先不看,这样是不是就很明白了
            // Objects.requireNonNull(after); // 这他喵的这接口里面不就只有accept()这一个抽象方法吗
            // return (T t) -> { accept(t); after.accept(t); }; // 这个单词已经在网络编程中见过了涩———— accept 接收
            }
            }

            通过看这个源码,其实什么是消费型函数式接口已经很明显了( 这里有一个注意点:别看这个方法是在做什么,而是应该关注:这个方法表达的逻辑是什么? )

            • accept 接收,那在现实生活中,爪子是接收? ———— 拿个东西给别人,别人要接收吧
              • 所以:void accept( T t )所表达的意思已经非常非常明显了 ———— 如果:还有点懵,那么改动一下 void accept( Object obj ) ————这里只是为了好理解所以用了Object,严格来讲:这个参数类型是由传进来的那个泛型决定的( 所以:注意是支持泛型的啊 )
                • 表明:
                  • 1、传递一个参数给接口,这个接口中的方法( 即:自己要写的业务代码 ),执行完之后,不需要返回值 ( 即:void )
                  • 2、传递进去的参数可以是任意类型
              • 因此:总结————lambda表达式可以执行的 消费者类型的函数式接口是指什么?
                • 使用方法时,这个方法的参数是一个接口类型的 ( 注:这个接口要保证只有一个抽象方法,不然lambda识别不了 ,是多个抽象方法的话,它不知道去找哪一个抽象方法)
                • 然后传递进去一个 / 多个 / 无参给你( lambda去执行的那个函数 ,即:接口中的那个抽象方法 ),lambda执行完之后不需要给我返回值 ( 即:中间写的那部分业务代码 ) ————这种接口类型的参数问题就可以使用lambda表达式来简化代码

 

      • 2、供给型( Supplier ),直接上源码
        • @FunctionalInterface
          public interface Supplier<T> { /**
          * Gets a result.
          *
          * @return a result
          */


          T get();

          }

          得出结论:

          • 传递的接口参数对应的接口中抽象方法是无参数、有返回值类型
        • 实例:就是前面对TreeSet集合改写排序规则那个例子就是,后面的实例不想写了
      • 3、断言型( Predicate ),上源码————这个接口别懵了,因为它里面还有其他的抽象方法( 但是真正属于这个接口的只有一个 )
        • @FunctionalInterface
          public interface Predicate<T> { /**
          * Evaluates this predicate on the given argument.
          *
          * @param t the input argument
          * @return {@code true} if the input argument matches the predicate,
          * otherwise {@code false}
          */
          boolean test(T t);
          }

          得出结论:

          • 给接口中的抽象方法传递一个任意类型的参数( 自己看情况决定是什么类型 ),然后返回一个boolean值
      • 4、函数型( Function ),也是直接上源码
        • @FunctionalInterface
          public interface Function<T, R> { /**
          * Applies this function to the given argument.
          *
          * @param t the function argument
          * @return the function result
          */


          R apply(T t); // R是返回值,t是参数

          }

          得出结论:

          • 给接口中的抽象方法传递一个参数、需要一个任意类型的返回值( 自己控制类型 )
      • lambda表达式的一些精要
        • javaSE高级篇5  —  java8新特性详解———更新完毕
      • lambda中的方法引用
        •         List<String> list = Arrays.asList("张三", "李四", "王五", "赵六");
          
                  // lambda用法
          // list.forEach( t-> System.out.println(t) ); // 这是正常玩的,另外forEach语句不说明,就是遍历的一个方法( 自行百度 ) // 方法引用
          list.forEach( System.out::println ); // 这是指:遍历list这个集合,然后打印出每一个值( 这里的System.out::println就是方法引用
             // ::就是引用的意思


2、Stream流,不是IO里面的那个流,这里是数据操作流( 也就是一个流程的流 )

  • 这个流程是个什么样的?
    • javaSE高级篇5  —  java8新特性详解———更新完毕
  • 1、来玩儿数据源( 即:创建流 )
      • package cn.xieGongZi.Stream;
        
        import java.util.ArrayList;
        import java.util.Arrays;
        import java.util.List;
        import java.util.stream.Stream; public class Demo { public static void main(String[] args) { // 创建流
        // 1、通过集合创建流( 最常用,这个东西应用的最多的地方也就是集合中 )
        // 先搞一个数据嘛————不过搞复杂一点儿( 因此:再来一个员工类 Employee ) // 开始准备填充数据
        //准备数据
        List<Employee> list = new ArrayList<>();
        list.add(new Employee("刘德华", "歌手", "男", 1200.0));
        list.add(new Employee("张旭阳", "演员", "男", 1400.0));
        list.add(new Employee("小沈阳", "演员", "男", 1300.0));
        list.add(new Employee("王宝强", "演员", "男", 1900.0));
        list.add(new Employee("姚明", "歌手", "男", 2200.0));
        list.add(new Employee("张杰", "主持人", "男", 3100.0));
        list.add(new Employee("范冰冰", "演员", "女", 4800.0));
        list.add(new Employee("范冰冰", "演员", "女", 4800.0)); // 创建流————1、集合创建
        Stream<Employee> stream1 = list.stream();
        System.out.println( stream1 ); // java.util.stream.ReferencePipeline$Head@4554617c,就是一个对象,看不出啥
        // 创建流嘛,看不出什么东西正常,也比较无聊 // 2、利用Arrays工具类创建
        // Arrays.stream(); // 但是:这个需要传递一个任意类型的数组
        Stream<Object> stream2 = Arrays.stream( list.toArray() );
        System.out.println( stream2 ); // java.util.stream.ReferencePipeline$Head@74a14482 // 3、利用stream接口来创建
        Stream<List<Employee>> stream3 = Stream.of(list);// of这里面是一个可变参数 / T类型的参数( 泛型 )
        // 所以类型就是依赖前面集合中创建的时候用的泛型类型
        System.out.println( stream3 ); // java.util.stream.ReferencePipeline$Head@1540e19d 都是一些对象,看不出啥子东西,玩起也无聊 }
        }
    package cn.xieGongZi.Stream;
    
    // 员工类
    public class Employee { private String name;
    private String job;
    private String sex;
    private Double salary; public Employee(String name, String job, String sex, Double salary) {
    this.name = name;
    this.job = job;
    this.sex = sex;
    this.salary = salary;
    } public String getName() {
    return name;
    } public void setName(String name) {
    this.name = name;
    } public String getJob() {
    return job;
    } public void setJob(String job) {
    this.job = job;
    } public String getSex() {
    return sex;
    } public void setSex(String sex) {
    this.sex = sex;
    } public Double getSalary() {
    return salary;
    } public void setSalary(Double salary) {
    this.salary = salary;
    } @Override
    public String toString() {
    return "Employee{" +
    "name='" + name + '\'' +
    ", job='" + job + '\'' +
    ", sex='" + sex + '\'' +
    ", salary=" + salary +
    '}';
    }
    }
    • 先提前知道一个点:即:流程图中的最后一环 —— 结束流程( 这里先了解一个forEach,其他的后面进行说明 )
      • 让这个点提前了解的原因是:
        • 这个流程创建了流之后,需要最后一步:结束流程,不然数据无法显示
          • // 终止流程 ———— 这个有结束流程 并 获取最终结果的功能 ———— 因此:先来了解一个终止方法
            // forEach()————这个方法就是遍历的意思。它需要一个消费型函数式接口
            stream1.forEach( (e)-> System.out.println(e) ); // 这里的这个e就是Employee类型的对象e
            // 再次解释一下这个流程
            // 首先:我们需要把一个类型的对象 当做参数 丢进去( 即:玩的匿名内部类new哪里————不就是一个对象吗 )
            // 然后:这个对象携带的参数( 信息 ) 就交给lambda表达式的某一个函数,让它去执行( 即:这里的forEach )
            // 而我们只需要做的事情就是:提供一种类型的对象参数,然后提供这个对象参数进到lambda要执行的函数中的业务代码是什么就行了( 即:这里的输出语句 )
  • 来正式开始玩儿这个流中的中间重要流程
    • 1、filter过滤 ————— 过滤是什么意思?———— 就是 筛选出我想要的信息涩
      • package cn.xieGongZi.Stream.playFilter;
        
        import cn.xieGongZi.Stream.Employee;
        
        import java.util.ArrayList;
        import java.util.List;
        import java.util.stream.Stream; public class Test { public static void main(String[] args) { //准备数据
        List<Employee> list = new ArrayList<>();
        list.add(new Employee("刘德华", "歌手", "男", 1200.0));
        list.add(new Employee("张旭阳", "演员", "男", 1400.0));
        list.add(new Employee("小沈阳", "演员", "男", 1300.0));
        list.add(new Employee("王宝强", "演员", "男", 1900.0));
        list.add(new Employee("姚明", "歌手", "男", 2200.0));
        list.add(new Employee("张杰", "主持人", "男", 3100.0));
        list.add(new Employee("范冰冰", "演员", "女", 4800.0));
        list.add(new Employee("范冰冰", "演员", "女", 4800.0)); // 创建流
        Stream<Employee> stream1 = list.stream(); // 开始玩儿filter
        // 1、假如我只想要list中的演员信息呢?
        System.out.println("获取list中的演员");
        stream1.filter( employee -> employee.getJob().equals("演员") ).forEach( System.out::println ); // 形参只有employee这一个,所以()直接省略
        // employee.getJob().equals("演员") 这个就是业务逻辑代码涩
        // 可以对照着 我们不知道这个lambda表达式,正常写这种问题的代码,这样理解更深
        System.out.println();
        System.out.println("正常代码写法");
        for (Employee employee : list) { if ( employee.getJob().equals("演员") ){
        System.out.println( employee );
        }
        } // 2、如果我想获得职业是演员,但是同时保证还是女的呢?
        System.out.println();
        System.out.println("获取list中的女演员");
        Stream<Employee> stream2 = list.stream(); // 这里重写开流,是因为前面那个已经利用forEach把流关闭了
        stream2.filter( employee -> employee.getJob().equals("演员") && employee.getSex().equals("女") ).forEach( System.out::println );
        // 这个过滤也就这么玩的,就不继续玩儿了 }
        }
      • 效果图如下:
        • javaSE高级篇5  —  java8新特性详解———更新完毕
    • 2、limit限制 ———— 什么意思? ———— 就是我只想显示特定的几条数据嘛 
      • package cn.xieGongZi.Stream.playLimit;
        
        import cn.xieGongZi.Stream.Employee;
        
        import java.util.ArrayList;
        import java.util.List;
        import java.util.stream.Stream; public class Demo { public static void main(String[] args) { // 准备数据
        List<Employee> list = new ArrayList<>();
        list.add(new Employee("刘德华", "歌手", "男", 1200.0));
        list.add(new Employee("张旭阳", "演员", "男", 1400.0));
        list.add(new Employee("小沈阳", "演员", "男", 1300.0));
        list.add(new Employee("王宝强", "演员", "男", 1900.0));
        list.add(new Employee("姚明", "歌手", "男", 2200.0));
        list.add(new Employee("张杰", "主持人", "男", 3100.0));
        list.add(new Employee("范冰冰", "演员", "女", 4800.0));
        list.add(new Employee("范冰冰", "演员", "女", 4800.0)); // 1、假如我只想要显示前5条数据呢?
        System.out.println("Stream流使用limit和lambda表达式进行操作");
        Stream<Employee> stream1 = list.stream(); stream1.limit(5).forEach( System.out::println ); System.out.println(); // 对比正常流程
        System.out.println("这是用正常流程进行遍历前5条数据");
        for (int i = 0; i < 5; i++) { System.out.println( list.get(i) );
        } // 2、那如果我只想要4、5条数据呢? ———— 用一个方法skip(),在多线程中已经介绍过这个方法了,作用也是一样的
        System.out.println();
        System.out.println("利用skip和lambda表达式获取stream流中指定那条 / 几条的信息");
        Stream<Employee> stream2 = list.stream();
        stream2.skip(3).limit(2).forEach(employee -> System.out.println( employee ) ); }
        }
      •  效果图如下:
        • javaSE高级篇5  —  java8新特性详解———更新完毕
    • 3、distinct 去重 ———— 去除重复的数据
      • 这个默认是根据Object类中的equals()来进行比较( 而这种默认比较的是值,所以只适合用值来去重,其他的东西需要去重的话,则:需要重写equals()方法,也就会伴随着重写hashCode,因此:这个不多做说明
    • 4、map投影 ———— 获取指定流中的某一部分组成的流 
      • package cn.xieGongZi.Stream.playMap;
        
        import cn.xieGongZi.Stream.Employee;
        
        import java.util.ArrayList;
        import java.util.List;
        import java.util.stream.Stream; public class Demo { public static void main(String[] args) { //准备数据
        List<Employee> list = new ArrayList<>();
        list.add(new Employee("刘德华", "歌手", "男", 1200.0));
        list.add(new Employee("张旭阳", "演员", "男", 1400.0));
        list.add(new Employee("小沈阳", "演员", "男", 1300.0));
        list.add(new Employee("王宝强", "演员", "男", 1900.0));
        list.add(new Employee("姚明", "歌手", "男", 2200.0));
        list.add(new Employee("张杰", "主持人", "男", 3100.0));
        list.add(new Employee("范冰冰", "演员", "女", 4800.0));
        list.add(new Employee("范冰冰", "演员", "女", 4800.0)); // 1、如果我只想要list中的所有的Job的信息呢?
        System.out.println("通过lambda和map映射流中的一部分内容");
        Stream<Employee> stream = list.stream();
        stream.map( employee -> employee.getJob() ).forEach( employee->System.out.println(employee) );
        }
        }
      •  效果图如下:
        • javaSE高级篇5  —  java8新特性详解———更新完毕
    • 5、Sorted排序
      • javaSE高级篇5  —  java8新特性详解———更新完毕

        可以得出:排序规则和treeSet一样的( 实现CompareTo接口 / 现写现用 ),所以,其实不太想进行说明

        • package cn.xieGongZi.Stream.playSorted;
          
          import cn.xieGongZi.Stream.Employee;
          
          import java.util.ArrayList;
          import java.util.List;
          import java.util.stream.Stream; public class Demo { public static void main(String[] args) { //准备数据
          List<Employee> list = new ArrayList<>();
          list.add(new Employee("刘德华", "歌手", "男", 1200.0));
          list.add(new Employee("张旭阳", "演员", "男", 1400.0));
          list.add(new Employee("小沈阳", "演员", "男", 1300.0));
          list.add(new Employee("王宝强", "演员", "男", 1900.0));
          list.add(new Employee("姚明", "歌手", "男", 2200.0));
          list.add(new Employee("张杰", "主持人", "男", 3100.0));
          list.add(new Employee("范冰冰", "演员", "女", 4800.0));
          list.add(new Employee("范冰冰", "演员", "女", 4800.0)); Stream<Employee> stream = list.stream();
          stream.sorted( ( employee1 , employee2)->
          employee1.getSalary() > employee2.getSalary() ? 1:-1).forEach(
          employee ->
          System.out.println(employee) );
          }
          }
        • 效果图如下:
          • javaSE高级篇5  —  java8新特性详解———更新完毕
    • 2、玩儿流程中的最后一项:终止操作
      • 1、forEach 前面已经玩过了,所以不玩了
      • 2、min  和 max ———— 获取流中最小 / 最小的那个对象信息 ———— 这个东西就和多线程中的那个异步结果Future一样
        • package cn.xieGongZi.Stream.close.min;
          
          import cn.xieGongZi.Stream.Employee;
          
          import java.util.ArrayList;
          import java.util.List; public class Demo { public static void main(String[] args) { //准备数据
          List<Employee> list = new ArrayList<>();
          list.add(new Employee("刘德华", "歌手", "男", 1200.0));
          list.add(new Employee("张旭阳", "演员", "男", 1400.0));
          list.add(new Employee("小沈阳", "演员", "男", 1300.0));
          list.add(new Employee("王宝强", "演员", "男", 1900.0));
          list.add(new Employee("姚明", "歌手", "男", 2200.0));
          list.add(new Employee("张杰", "主持人", "男", 3100.0));
          list.add(new Employee("范冰冰", "演员", "女", 4800.0));
          list.add(new Employee("范冰冰", "演员", "女", 4800.0));
          // 这个规则也是弄一个Comparator,所以还可以对照treeSet的排序原理来理解
          Employee employee = list.stream().min((employee1, employee2) -> employee1.getSalary() > employee2.getSalary() ? 1 : -1).get();
          System.out.println(employee);
          System.out.println();

          Employee employee3 = list.stream().max((employee1, employee2) -> employee1.getSalary() > employee2.getSalary() ? 1 : -1).get();
          System.out.println(employee3);
          }
          }


      • 3、count ———— 获取流中的信息对象有多少个
        • package cn.xieGongZi.Stream.close.count;
          
          import cn.xieGongZi.Stream.Employee;
          
          import java.util.ArrayList;
          import java.util.List; public class Demo { public static void main(String[] args) { //准备数据
          List<Employee> list = new ArrayList<>();
          list.add(new Employee("刘德华", "歌手", "男", 1200.0));
          list.add(new Employee("张旭阳", "演员", "男", 1400.0));
          list.add(new Employee("小沈阳", "演员", "男", 1300.0));
          list.add(new Employee("王宝强", "演员", "男", 1900.0));
          list.add(new Employee("姚明", "歌手", "男", 2200.0));
          list.add(new Employee("张杰", "主持人", "男", 3100.0));
          list.add(new Employee("范冰冰", "演员", "女", 4800.0));
          list.add(new Employee("范冰冰", "演员", "女", 4800.0));

          System.out.println( list.stream().count() );

          System.out.println(); // 还可以配合着玩儿
          System.out.println( list.stream().filter( employee -> employee.getSex().equals("男") ).count() );
          }
          }

           效果图如下:

          • javaSE高级篇5  —  java8新特性详解———更新完毕
      • 4、collect ———— 收集 ———— 这个玩意儿需要一个容器把结果装起来( 因此需要用到Collectors工具类 )
          • javaSE高级篇5  —  java8新特性详解———更新完毕
        package cn.xieGongZi.Stream.close.collect;
        
        import cn.xieGongZi.Stream.Employee;
        
        import java.util.ArrayList;
        import java.util.List;
        import java.util.stream.Collectors; public class Demo { public static void main(String[] args) { //准备数据
        List<Employee> list = new ArrayList<>();
        list.add(new Employee("刘德华", "歌手", "男", 1200.0));
        list.add(new Employee("张旭阳", "演员", "男", 1400.0));
        list.add(new Employee("小沈阳", "演员", "男", 1300.0));
        list.add(new Employee("王宝强", "演员", "男", 1900.0));
        list.add(new Employee("姚明", "歌手", "男", 2200.0));
        list.add(new Employee("张杰", "主持人", "男", 3100.0));
        list.add(new Employee("范冰冰", "演员", "女", 4800.0));
        list.add(new Employee("范冰冰", "演员", "女", 4800.0)); // 1、低级使用
        System.out.println("低级使用");
        List<Employee> collect = list.stream().collect( Collectors.toList() );
        System.out.println( collect );
        System.out.println(); // 2、配合其他的中间操作使用
        System.out.println("灵活使用");
        List<Employee> resultCollect = list.stream().filter( employee -> employee.getSex().equals("女"
        ) ).collect( Collectors.toList() );
        System.out.println( resultCollect );

        }
        }

         效果图如下:

        javaSE高级篇5  —  java8新特性详解———更新完毕

         这个东西补充一个点:利用Conllects工具类在这里还可以实现分组 ——— group

        • 而这个的思想就是利用了map集合的思想———— key-value双列存储,但是更复杂( 来个图看一下 )
          • javaSE高级篇5  —  java8新特性详解———更新完毕

             实例:

            • package cn.xieGongZi.Stream.close.collect.group;
              
              import cn.xieGongZi.Stream.Employee;
              
              import java.util.ArrayList;
              import java.util.List;
              import java.util.Map;
              import java.util.stream.Collectors; public class Play { public static void main(String[] args) { //准备数据
              List<Employee> list = new ArrayList<>();
              list.add(new Employee("刘德华", "歌手", "男", 1200.0));
              list.add(new Employee("张旭阳", "演员", "男", 1400.0));
              list.add(new Employee("小沈阳", "演员", "男", 1300.0));
              list.add(new Employee("王宝强", "演员", "男", 1900.0));
              list.add(new Employee("姚明", "歌手", "男", 2200.0));
              list.add(new Employee("张杰", "主持人", "男", 3100.0));
              list.add(new Employee("范冰冰", "演员", "女", 4800.0));
              list.add(new Employee("范冰冰", "演员", "女", 4800.0)); Map< String, List<Employee> > group = list.stream().collect( Collectors.groupingBy(employee -> employee.getJob() ) );
              // 这里泛型的泛型 ———— 套娃 ———— 即:整个内容是存在一个map中的
              // 而这个map中的key就是job,value就是每一个职业对应有哪些人
              // String就是key 职业的类型,list集合中就是存的这个职业对应的是那些人,类型嘛,就是Employee类型咯 for ( String key : group.keySet() ) { System.out.println( key + " = " + group.get(key) ); }
              }
              }

              效果图如下:

              • javaSE高级篇5  —  java8新特性详解———更新完毕


至此,java8的新特性就整完了,其他的特性也有,只是那些懒得说明了,因为最常用的是这些,其他那些有基础知识之后,需要用时一看就会了

另外:现在已经是java10几了,所以严格来讲,这些根本不叫新特性 ^ _ ^

javaSE高级篇5  —  java8新特性详解———更新完毕

javaSE高级篇5 — java8新特性详解———更新完毕的更多相关文章

  1. java8新特性详解&lpar;转&rpar;

    原文链接. 前言: Java 8 已经发布很久了,很多报道表明Java 8 是一次重大的版本升级.在Java Code Geeks上已经有很多介绍Java 8新特性的文章,例如Playing with ...

  2. Java学习之&equals;&equals;&gt&semi;Java8 新特性详解

    一.简介 Java 8 已经发布很久了,很多报道表明Java 8 是一次重大的版本升级.Java 8是 Java 自 Java 5(发布于2004年)之后的最重要的版本.这个版本包含语言.编译器.库. ...

  3. javaSE高级篇4 — 反射机制&lpar; 含类加载器 &rpar; — 更新完毕

    反射机制 1.反射机制是什么?----英文单词是:reflect.在java.lang包下---这才是java最牛逼的技术 首先提前知道一句话----在java中,有了对象,于是有了类,那么有了类之后 ...

  4. 点击--》java9 新特性 详解

    引言: 点击-->java9 新特性 详解 点击-->java8 新特性 详解 正题: 1.局部变量var 将前端思想var关键字引入java后段,自动检测所属于类型,一种情况除外,不能为 ...

  5. java10 新特性 详解

    引言: 点击-->java9 新特性 详解 点击-->java8 新特性 详解 正题: 1.局部变量var 将前端思想var关键字引入java后段,自动检测所属于类型,一种情况除外,不能为 ...

  6. Java8 Stream新特性详解及实战

    Java8 Stream新特性详解及实战 背景介绍 在阅读Spring Boot源代码时,发现Java 8的新特性已经被广泛使用,如果再不学习Java8的新特性并灵活应用,你可能真的要out了.为此, ...

  7. Java基础学习总结(33)——Java8 十大新特性详解

    Java8 十大新特性详解 本教程将Java8的新特新逐一列出,并将使用简单的代码示例来指导你如何使用默认接口方法,lambda表达式,方法引用以及多重Annotation,之后你将会学到最新的API ...

  8. Java9 新特性 详解

    作者:木九天   <   Java9 新特性 详解  > Java9 新特性 详解 摘要: 1.目录结构 2.repl工具 jShell命令 3.模块化 4.多版本兼容jar包 5.接口方 ...

  9. ES6&comma;ES2105核心功能一览&comma;js新特性详解

    ES6,ES2105核心功能一览,js新特性详解 过去几年 JavaScript 发生了很大的变化.ES6(ECMAScript 6.ES2105)是 JavaScript 语言的新标准,2015 年 ...

随机推荐

  1. 51Nod 1766 树上的最远点对

    Description 一棵树,询问两个端点编号分别在在 \([a,b]\) 和 \([c,d]\) 两个区间中的最长链. Sol 线段树+ST表. 树上最长链可以合并,只需要合并两个区间最长链的两个 ...

  2. ☀【CSS3】box-sizing

    <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8& ...

  3. javascript基础学习(二)

    javascript的数据类型 学习要点: typeof操作符 五种简单数据类型:Undefined.String.Number.Null.Boolean 引用数据类型:数组和对象 一.typeof操 ...

  4. Linux企业级项目实践之网络爬虫(30)——通过查阅RFC文档扩充更加复杂的功能

    HTTP是一种很简单的请求.响应式协议,客户端发送一个请求.服务器返回一个响应.HTTP 1.1 版本规范由 RFC2616 定义.了解了 HTTP请求.响应消息在TCP数据流中的格式,很容易使用纯 ...

  5. webpack&plus;vue打包之后输出配置文件修改接口文件

    用vue-cli构建的项目通常是采用前后端分离的开发模式,也就是前端与后台完全分离,此时就需要将后台接口地址打包进项目中,but,难道我们只是改个接口地址也要重新打包吗?当然不行了,那就太麻烦了,怎么 ...

  6. C&num;基础系列——语法

    1.C#是这样开始的: 函数入口:static void  Main(String [] args){} 2.Hello  World 例子 using system;--------导入命名空间,里 ...

  7. nodeJs实现微信小程序的图片上传

    今天我来介绍一下nodejs如何实现保存微信小程序传过来的图片及其返回 首先wx.uploadFile绝大部分时候是配合wx.chooseImage一起出现的,毕竟选择好了图片,再统一上传是实现用户图 ...

  8. 安卓程序代写 网上程序代写&lbrack;原&rsqb;Android项目中string&period;xml占位符

    开发中经常遇到这样的情况 , 在string.xml中用到以下占位符 <string name="delete_success">删除<xliff:g id=&q ...

  9. c&plus;&plus; imooc自学计划

    一.视频学习相关的课程列表: C++远征之起航篇http://www.imooc.com/learn/342: C++远征之离港篇http://www.imooc.com/learn/381: C++ ...

  10. js&lowbar;在原有的日期上添加天数输出添加后的日期

    开始编码工作也有段时间了,想想没有留下点什么,有点遗憾.学到的一些经验,写写,分享一下.也给自己整理一下. 今天分享一下,在原有的日期上添加天数输出添加后的日期.开始做的时候,简单的思路是,直接用ne ...