您好,欢迎访问代理记账网站
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

Java8的新特性

java8的新特性

1.几个常用特性

1.Lambda表达式

2.方法引用

3.默认方法

4.新工具

5.StreamApi

6.Date Time Api

7.Optional   解决了空指针异常

8.Nashorn,javaScript引擎

2.Lambda表达式的基本用法

1.初识:使用Lambda表达式实现一个线程

public static void testRunnable(){
	//古老写法
	Runnable runnable = new Runnable(){
		@Override
            public void run() {
                log.info("aaaaa");
            }
	};
	// 启动线程
    new Thread(runnable).start();
    
    // lambda写法 ,可以写多个,使用 ->{}  ->:操作符
    // @FunctionalInterface 检测是否函数式接口,里面只能有一个方法
        Runnable runnable1 = () -> log.info("bbbb");
	// 启动线程
        new Thread(runnable1).start();
}

2.Lambda表达式的基本用法

/**
基本用法:
	lambda表达式格式:() -> {}
	-> :操作符,指向方法的实现内容
	左边:Lambda表达式的形参列表(实际就是函数式接口中唯一的那个方法的形参列表)
	右边:Lambda表达式的执行体(实际上就是函数式接口中唯一的那个方法的实现)
*/

// 使用java8提供的消费型接口来显示Lambda表达的几个简化写法

--------------------------原始写法,带一个参数----------------------------
    Consumer<String> consumer1 = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println("消费数据:"+ s);
            }
        };
     consumer1.accept("consumer接口,没用使用lambda表达式");
    
------------------Lambda表达式写法,带一个参数,没有返回值--------------------
// 写法1:
Consumer<String> consumer2 = (String s) -> {
            System.out.println(s);
        };
   consumer2.accept("consumer接口,使用lambda表达式");

// 写法2:省略参数类型,java8类型自动推断 list集合(泛型)
Consumer<String> consumer3 = (s) -> {
            System.out.println(s);
        };
 consumer3.accept("consumer接口,使用lambda表达式,省略参数类型");

// 写法3:省略参数类型,java8类型自动推断,如果只有一个参数,可以省略小括号
Consumer<String> consumer4 = s -> {
            System.out.println(s);
        };
consumer4.accept("consumer接口,使用lambda表达式,省略参数类型,一个参数省略小括号");

// 写法4:省略参数类型,java8类型自动推断,如果只有一个参数,可以省略小括号,如果方法实现只有一条语句(不论有没有返回值),可以省略大括号
Consumer<String> consumer5 = s -> System.out.println(s);
consumer5.accept("consumer接口,使用lambda表达式,省略参数类型,一个参数省略小括号,如果只有一条语句,省略大括号");

// 写法5:省略参数类型,java8类型自动推断,如果只有一个参数,可以省略小括号,如果方法实现只有一条语句(不论有没有返回值),可以省略大括号;使用方法引用
Consumer<String> consumer6 = System.out::println;
consumer6.accept("consumer接口,使用lambda表达式,省略参数类型,一个参数省略小括号,如果只有一条语句,省略大括号;使用方法引用,省略参数指定");


------------------Lambda表达式写法,带多个参数,有返回值--------------------
// 普通写法
Comparator<Integer> comparator1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        };
 System.out.println(comparator1.compare(12,13));

 // 写法1,省略参数类型,由于有多个参数,不可以省略小括号   
Comparator<Integer> comparator2 = (o1,o2) -> o1.compareTo(o2);
System.out.println(comparator2.compare(15,13));   

// 写法2,使用方法引用
Comparator<Integer> comparator3 = Integer::compareTo;
System.out.println(comparator3.compare(14,14));    
    
// 写法3,省略参数类型,多行语句不可以省略大括号
Comparator<Integer> comparator4 = (o1,o2) -> {
            System.out.println("值1:"+o1);
            System.out.println("值1:"+o2);
            return o1.compareTo(o2);
        };
 System.out.println(comparator4.compare(16,18));

3.函数式接口使用

1.消费型函数式接口–Consumer

//Consumer  --方法中带参数,没有返回值 

static void  testLambdaConsumer(){
     	 // 消费
        consumData(1000,money -> System.out.println("我有1000块,去买彩票"));
        consumData(2000,money -> {
            System.out.println("我有2000块,先去网吧打游戏");
            System.out.println("我有2000块,打完游戏去超市买东西");
        });
    }
static  void  consumData(double money,Consumer<Double> consumer){
        consumer.accept(money);
    }

2.供给型函数式接口–Supplier

// Supplier --没有参数,可以返回任何的类型结果
static  void  testLambdaSupplier(){
        Supplier<String> supplier = () -> "供给自定义数据返回";
        System.out.println(supplier.get());

        // 调用带有供给型接口方法,自定义返回
        System.out.println(getDataBySupplier( () -> "123" ));
        System.out.println(getDataBySupplier( () -> "bdc" ));

    }

    static String getDataBySupplier(Supplier<String> supplier){
        return  supplier.get();
    }

3. 断言型函数式接口 --Predicate

// Predicate --有一个参数,返回boolean的方法
static void testLambdaPredicate(){
      // 定义一个姓名集合
  List<String> names = Arrays.asList("Tom","Jack","Merry","mark","LiLei","XieQun");
    
      // 需要给我返回一个包含小写字母a的姓名集合
  List<String> namesList1 = collectNamesList(names, name -> name.contains("a") );
        System.out.println(namesList1);
    
      // 需要给我返回一个包含小写字母a的姓名集合或者e的姓名集合
  List<String> namesList2 = collectNamesList(names,name -> name.contains("a") || name.contains("e") );
        System.out.println(namesList2);
    }

    static List<String> collectNamesList(List<String> names,Predicate<String> predicate){
        // 定义一个返回的集合
        List<String> namesList = new ArrayList<>();

        // 使用断言型接口,在调用此发给发处,指定规则
        names.forEach(name -> {
            // test方法的实现,在调用collectNamesList方法处,指定的
            if(predicate.test(name)){
                namesList.add(name);
            }
        });
        return namesList;
    }

4.函数式接口 --Function

// Function -- 有两个参数,一个是入参,还有一个返回值
static  void  testLambdaFunction(){
        Function<Double,Long> function1 = d -> Math.round(d);
        Long num = function1.apply(2346.556);
        System.out.println(num);
    }

4.StreamApi

什么是Stream

什么是 Stream?
Stream(流)是一个来自数据源的元素队列并支持聚合操作

元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。

数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。

聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
和以前的Collection操作不同, Stream操作还有两个基础的特征:

Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。

内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。

1.基本用法

static  void testStream1(){
        // 1-5 每个数字的平方
        Stream.of(1,2,3,4,5).forEach(i -> System.out.println(i*i));

        // 求数组最大值
        int[] nums = {2,33,12,44};
        System.out.println(Arrays.stream(nums).max().getAsInt());

        // 从1开始,前10个奇数--iterate
        Stream.iterate(1,num -> num+2).limit(10).forEach(System.out::println);

        // 生成10个随机数--generate
        Stream.generate(Math::random).limit(10).forEach(System.out::println);
    }

2.操作集合,集合流遍历

static void testStream2(){
        // 获取工资大于7000的员工
        Stream<Employee> employeeStream = EmployeeUtil.employees.stream();
        employeeStream.forEach(employee -> {
            if(employee.getEmpSalary() >= 7000){
                System.out.println(employee);
            }
        });
    }

3.流对集合数据的操作

static void testStream3(){
   // filter 晒选工资大于6000,且年龄小于等于30的员工  foreach()结束六的操作
        Stream<Employee> employeeStream = EmployeeUtil.employees.stream();
        employeeStream.filter(employee -> employee.getEmpSalary() >= 6000).filter(employee -> employee.getEmpAge() <= 30).forEach(System.out::println);

        System.out.println("--------------------------------------");
  // limit :截断,根据指定的数量(最大数量),获取对应的数量元素
        Stream<Employee> employeeStream2 = EmployeeUtil.employees.stream();
        employeeStream2.limit(3).forEach(System.out::println);

        System.out.println("--------------------------------------");
  // skip; 过滤,过滤掉前面指定数量的元素
        Stream<Employee> employeeStream3 = EmployeeUtil.employees.stream();
        employeeStream3.skip(2).forEach(System.out::println);

        System.out.println("--------------------------------------");
  // distinct -去重,主要对象的hashcode和equals方法
        Stream<Integer> integerStream = Stream.of(11,22,33,44,55,66,33,44);
        integerStream.distinct().forEach(System.out::println);
    
  // map: 将集合元素元素转换格式或者信息提取,自动将规则作用到每个元素上,映射成新的元素集合  
    	List<String> stringList = Arrays.asList("tom","jack","maek");
        stringList.stream().map(String::toUpperCase).forEach(System.out::println);
    	 // 将员工集合中姓名长度大于五的员工姓名输出
    	 Stream<Employee> employeeStream = EmployeeUtil.employees.stream();
        		employeeStream.map(Employee::getEmpName).filter(string -> 					string.length() > 5 ).forEach(System.out::println);	
    
// mapToInt:产生是int的流    
    EmployeeUtil.employees.stream().mapToInt(emp -> 										emp.getEmpName().length()).forEach(System.out::println);
    
  
   
    // sorted:元素排序 默认升序
    	List<String> stringList = Arrays.asList("tom","jack","maek");
        stringList.stream().sorted().forEach(System.out::println);
    
   // 定制排序:先按照年龄排序,如果年龄相同,再按工资排序
    	EmployeeUtil.employees.stream().sorted( (e1,e2) -> {
            int cmpResult = Integer.compare(e1.getEmpAge(),e2.getEmpAge());
            if (cmpResult == 0){
                return Double.compare(e1.getEmpSalary(),e2.getEmpSalary());
            }
            return cmpResult;
        }).forEach(System.out::println);
    
    
   // 匹配和查找
   // 判断员工中有没有小于20岁的人
    
   // anyMatch:至少要匹配到一个,返回true
  		 boolean anyMatchFlag =  EmployeeUtil.employees.stream().anyMatch(emp -> emp.getEmpAge() < 20);
        System.out.println("有没有员工年龄小于20岁" + anyMatchFlag);
    
    // allMatch:全匹配,返回true 
    // 判断员工中,是不是所有人的工资都大于4000
    	 boolean allMatchFlag = EmployeeUtil.employees.stream().allMatch(emp -> emp.getEmpSalary() > 4000);
        System.out.println("所有人的工资都大于4000》:" + allMatchFlag);
    
    // noneMatch:没有一个员工满足,返回true
    // 判断员工中,是否有人的姓名是7结尾的
    	boolean noneMatchFlag = EmployeeUtil.employees.stream().noneMatch(emp -> emp.getEmpName().endsWith("7"));
        System.out.println("没有人的姓名已7结尾:" + noneMatchFlag);
    
 
    // count:返回集合的数量
    // 统计员工中,工资大于6000的有多少人
    Long userCount = EmployeeUtil.employees.stream().filter(emp -> emp.getEmpSalary() > 6000).count();
        System.out.println("员工工资大于6000的有多少人:" + userCount);
    
    // findFirst:返回集合中第一个元素
    	Optional<Employee> emp1 = EmployeeUtil.employees.stream().findFirst();
        System.out.println(emp1);
    
    // findAny: 返回集合中任意一个元素
        Optional<Employee> emp2 = EmployeeUtil.employees.stream().findAny();
        System.out.println(emp2);
    
    // max: 比较最大值
    // 获取员工中的最高工资
        Optional<Double> maxMoney = EmployeeUtil.employees.stream().map(Employee::getEmpSalary).max(Double::compareTo);
        System.out.println(maxMoney);
    
    // min :比较最小值
    // 获取员工中的最低工资的人
        Optional<Employee> emp3 = EmployeeUtil.employees.stream().min(Comparator.comparingDouble(Employee::getEmpSalary));
        System.out.println(emp3);
    
    // collect: 收集  将查询的内容转成一个新集合
    // 查找员工中,年龄大于30的员工,存入新的集合返回
    List<Employee> employees = EmployeeUtil.employees.stream().filter(emp -> emp.getEmpAge()>30).collect(Collectors.toList());
        employees.forEach(System.out::println);
    
}
    

集合规约

 // reduce 规约,求集合中数字的总和
        List<Integer> numList = Arrays.asList(1,3,5,7,9);
        Optional<Integer> sum1 = numList.stream().reduce( (x,y) -> x+y );
        System.out.println(sum1);
        Optional<Integer> sum2 = numList.stream().reduce(Integer::sum);
        System.out.println(sum2);

        Optional<Integer> sum3 = numList.stream().reduce(( a,b) -> {
            System.out.println("a="+b);
            a += b;
            System.out.println("b="+b);
            System.out.println("a_a="+a);
            return a;
        });
        System.out.println(sum3);

        // 计算所有员工工资总和
        Optional<Double> totalMoney = EmployeeUtil.employees.stream().map(Employee::getEmpSalary).reduce(Double::sum);
        System.out.println(totalMoney);

        // 规约,求集合中数字的平方总和
        List<Integer> numList2 = Arrays.asList(2,4,6,8,10);
        Optional<Integer> sum4 = numList2.stream().map(num -> num*num).reduce(Integer::sum);
        System.out.println(sum4);

4. streamApi 统计


// foreach: 遍历集合输出  会结束流
// collect: 收集  将查询的内容转成一个新集合
// filter 晒选工资大于6000,且年龄小于等于30的员工  foreach()结束流的操作
// limit :截断,根据指定的数量(最大数量),获取对应的数量元素
// skip; 过滤,过滤掉前面指定数量的元素
// distinct -去重,主要对象的hashcode和equals方法
// mapToInt:产生是int的流    
// map: 将集合元素元素转换格式或者信息提取,自动将规则作用到每个元素上,映射成新的元素集合 // sorted:元素排序 默认升序 
// anyMatch:至少要匹配到一个,返回true
// allMatch:全匹配,返回true 
// noneMatch:没有一个员工满足,返回true
// count:返回集合的数量
// findFirst:返回集合中第一个元素
// findAny: 返回集合中任意一个元素
// max: 比较最大值
// min :比较最小值
// reduce 规约,求集合中数字的总和 reduce(a ,b) a+b (a+b)+b

5.Optional 解决空指针的问题

接受一个指定的元素
 Optional<Employee>  解决空指针的问题

6.自定义函数式接口

/*函数式接口定义:
	如果一个接口,只有一个抽象方法,则该接口就是函数式接口(1.8之后在接口中加入了默认方法)
 	 @FunctionalInterface 加了此注解,说明这个接口是函数式接口,如果不是,该注解报错*/

@FunctionalInterface
public interface MyFunctionInterface {

    void sayHi(String str);

    default  void sayHello(){
        System.out.println("这个是默认方法,可以通过接口直接调用");

    }

}


测试自定义函数式接口 ,该接口可以带一个参数
static  void  testFunctionInterface(MyFunctionInterface myFunctionInterface,String msg){
        myFunctionInterface.sayHi(msg);
         myFunctionInterface.sayHello();

        }


分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进