• JavaSE JDK新特性


    JDK8的新特性:

    Lambda表达式与Functional接口

    在JDK8之前,Java是不支持函数式编程的,所谓的函数编程,即可理解是将一个函数(也称为“行为”)作为一个参数进行传递。通常我们提及得更多的是面向对象编程,面向对象编程是对数据的抽象(各种各样的POJO类),而函数式编程则是对行为的抽象(将行为作为一个参数进行传递)。在JavaScript中这是很常见的一个语法特性,但在Java中将一个函数作为参数传递这却行不通,好在JDK8的出现打破了Java的这一限制

    Lambda表达式由3部分组成:

     参数  ->  函数体

    能够接收Lambda表达式的参数类型,是一个只包含一个方法的接口。只包含一个方法的接口称之为“函数接口

    package com.xk;
    /*
     *作者:吴志龙
     *日期:2018年8月17日  
    */
    /**
     * 只有一个抽象方法的接口是函数式接口。
     * @author 27783
     *
     */
    public interface Lambad {
        
        
        public void add();
    
    }
    View Code
    package com.xk;
    /*
     *作者:吴志龙
     *日期:2018年8月17日  
    */
    public class LambadDemo {
        
        public static void test(Lambad lambad){
            lambad.add();
        }
        
        
    //现在我要执行add方法但是我没有实现类
    //我们知道可以使用匿名内部类
        
        public static void main(String[] args) {
            //匿名内部类的写法
            test(new Lambad() {
                
                @Override
                public void add() {
                     System.out.println(10+5);
                    
                }
            });
            
            //使用lambad表达式
            
            test(() -> {System.out.println(10+5);});
        }
        
    
    }
    View Code

    可以看到,只要是一个接口中只包含一个方法,则可以使用Lambda表达式,这样的接口称之为“函数接口”。

      上面的函数接口比较简单不包含参数,也不包含返回值

    有参无返回值的:

     

    package com.xk;
    /*
     *作者:吴志龙
     *日期:2018年8月17日  
    */
    /**
     * 只有一个抽象方法的接口是函数式接口。
     * @author 27783
     *
     */
    public interface Lambad {
        
        
        public void add(int a,int b);
    
    }
    View Code
    package com.xk;
    /*
     *作者:吴志龙
     *日期:2018年8月17日  
    */
    public class LambadDemo {
        
        public static void test(Lambad lambad){
            int a=10;int b=20;
            lambad.add(a,b);
        }
        
        
    //现在我要执行add方法但是我没有实现类
    //我们知道可以使用匿名内部类
        
        public static void main(String[] args) {
             //匿名内部类
            test(new Lambad() {
                
                @Override
                public void add(int a, int b) {
                     System.out.println(a+b);
                    
                }
            });
            
            //使用lambad表达式
             test((a,b) ->{System.out.println(a+b);});
         
        }
        
    
    }
    View Code

    有参有返回值:

    package com.xk;
    /*
     *作者:吴志龙
     *日期:2018年8月17日  
    */
    /**
     * 只有一个抽象方法的接口是函数式接口。
     * @author 27783
     *
     */
    public interface Lambad {
        
        
        public int add(int a,int b);
    
    }
    View Code
    package com.xk;
    /*
     *作者:吴志龙
     *日期:2018年8月17日  
    */
    public class LambadDemo {
        
        public static int test(Lambad lambad){
            int a=10;int b=20;
            int c=lambad.add(a,b);
             
            return c;
        }
        
        
    //现在我要执行add方法但是我没有实现类
    //我们知道可以使用匿名内部类
        
        public static void main(String[] args) {
             //匿名内部类
            test(new Lambad() {
                
                @Override
                public int add(int a, int b) {
                      
                    return a+b;
                }
            });
            
            //使用lambad表达式
            int c=test((a,b) -> {return a+b;} );
            System.out.println(c);
        }
        
    
    }
    View Code

    使用泛型:

    package com.xk;
    /*
     *作者:吴志龙
     *日期:2018年8月17日  
    */
    /**
     * 只有一个抽象方法的接口是函数式接口。
     * @author 27783
     *
     */
    public interface Lambad<T> {
        
        
        public int add(T a,T b);
    
    }
    View Code
    package com.xk;
    /*
     *作者:吴志龙
     *日期:2018年8月17日  
    */
    public class LambadDemo {
        
        public static int test(Lambad<Integer> lambad){
            int a=10;int b=20;
            int c=lambad.add(a,b);
             
            return c;
        }
        
        
    //现在我要执行add方法但是我没有实现类
    //我们知道可以使用匿名内部类
        
        public static void main(String[] args) {
    //         //匿名内部类
    //        test(new Lambad<Integer>() {
    //
    //            @Override
    //            public int add(Integer a, Integer b) {
    //                // TODO Auto-generated method stub
    //                return a+b;
    //            }
    //        });
            
            //使用lambad表达式
            int c=test((Integer a, Integer b) -> {return a+b;} );
            System.out.println(c);
        }
        
    
    }
    View Code

    使用泛型后,在我们使用的时候,注意要设置参数的类型,不设置的化,系统会自动根据上下文来推导这个数据类型,但是最好还是写上。

    这三种基本情况已经大致清楚了,特别是需要弄清,什么时候可以使用Lambda表达式代替匿名内部类,也就是Lambda表达式的应用场景是函数接口。Lambda表达式这一新特性在JDK8中的引入,更大的好处则是集合API的更新,新增的Stream类库,使得我们在遍历使用集合时不再像以往那样不断地使用for循环

    stream:

    在jdk8中引入了新的概念:

     流是Java8引入的全新概念,它用来处理集合中的数据,我们可以把他理解为一种高级集合。

    我们知道集合的一些操作很麻烦,需要写大量的代码 而流是以声明的形式操作集合,它就像SQL语句,我们只需告诉流需要对集合进行什么操作,它就会自动进行操作,并将执行结果交给你,无需我们自己手写代码。

    因此,流的集合操作对我们来说是透明的,我们只需向流下达命令,它就会自动把我们想要的结果给我们。由于操作过程完全由Java处理,因此它可以根据当前硬件环境选择最优的方法处理,我们也无需编写复杂又容易出错的多线程代码了。

    流的特点:

        只能遍历一次。流在使用一次后就会关闭了,我们无法进行下一次操作了。当然我们可以重新去开始一个流,进行操作。

        采用内部迭代方式。若要对集合进行处理,则需我们手写处理代码,这就叫做外部迭代。而要对流进行处理,我们只需告诉流我们需要什么结果,处理过程由流自行完成,这就称为内部迭代。

    流的操作分为两种,分别为中间操作 和 终端操作。

      1. 中间操作
        当数据源中的数据上了流水线后,这个过程对数据进行的所有操作都称为“中间操作”。
        中间操作仍然会返回一个流对象,因此多个中间操作可以串连起来形成一个流水线。

      2. 终端操作
        当所有的中间操作完成后,若要将数据从流水线上拿下来,则需要执行终端操作。
        终端操作将返回一个执行结果,这就是你想要的数据。

    流的操作过程

    使用流一共需要三步:

    1. 准备一个数据源
    2. 执行中间操作
      中间操作可以有多个,它们可以串连起来形成流水线。
    3. 执行终端操作
      执行终端操作后本次流结束,你将获得一个执行结果。

     流的使用:

       在使用流之前,首先需要拥有一个数据源,并通过StreamAPI提供的一些方法获取该数据源的流对象。数据源可以有多种形式:集合、数组、多个值、文件。

    package com.xk;
    
    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.stream.Stream;
    
    /*
     *作者:吴志龙
     *日期:2018年8月17日  
    */
    public class StreamDemo {
        
        //Stream的一些操作
        public static void main(String[] args) {
            //集合获取流
            List<Integer> list = new ArrayList<Integer>();
            
            Stream<Integer> stem=list.stream();
            
            //数组获取流
            String[]  name={"悟空","八戒","悟净"};
            
            Stream<String> result=Arrays.stream(name);
            
            
            //值获取流
            Stream<String> ste = Stream.of("悟空","八戒","悟净");
        
            //文件操作获取流
            
            try {
                Stream stream=Files.lines(Paths.get("路径名"));
                 
    
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
                
     
            
            
        }
    
    }
    View Code

    流的操作:这里我们主要使用集合操作。

    package com.xk;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Collections;
    import java.util.List;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;
    
    /*
     *作者:吴志龙
     *日期:2018年8月17日  
    */
    public class StreamTest {
    
        public static void main(String[] args) {
            List<Integer> list = new ArrayList<Integer>();
    
            // 筛选操作:filter
            List<Integer> result = list.stream().filter(temp -> temp < 10).collect(Collectors.toList());
    
            // 去重
            List<Integer> result = list.stream().distinct().collect(Collectors.toList());
    
            // 截取:截取多少个元素:最大不能超过 list.size();
    
            List<Integer> result = list.stream().limit(5).collect(Collectors.toList());
    
            // 跳过多少个元素
    
            List<Integer> result = list.stream().skip(4).collect(Collectors.toList());
    
        }
    
    }
    View Code
    package com.xk;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Collections;
    import java.util.List;
    import java.util.Optional;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;
    
    /*
     *作者:吴志龙
     *日期:2018年8月17日  
    */
    public class StreamTest {
    
        public static void main(String[] args) {
            List<Student> list = new ArrayList<Student>();
            Student student1 = new Student("八戒", 500);
            Student student = new Student("悟空", 500);
    
            Student student2 = new Student("悟静", 500);
            list.add(student1);
            list.add(student);
    
            list.add(student2);
            // 对流中的每个元素执行一个函数,
            // 使得元素转换成另一种类型输出。
            // 流会将每一个元素输送给map函数,
            // 并执行map中的Lambda表达式,
            // 最后将执行结果存入一个新的流中
            List<String> result = list.stream().map(Student::getName).collect(Collectors.toList());
            result.forEach(temp -> {
                System.out.println(temp);
            });
    
            // 是否匹配任一元素
            // anyMatch用于判断流中是否存在至少一个元素满足指定的条件,
            // 这个判断条件通过Lambda表达式传递给anyMatch,执行结果为boolean类型
    
            boolean flag = list.stream().anyMatch((temp) -> temp.getName().equals("悟空"));
            System.out.println(flag);
            // findAny能够从流中随便选一个元素出来,它返回一个Optional类型的元素。
            Optional<Student> option = list.stream().findAny();
    
        }
    
    }
    View Code

     

    Optional介绍

    Optional是Java8新加入的一个容器,这个容器只存1个或0个元素,它用于防止出现NullpointException,它提供如下方法:

    • isPresent()
      判断容器中是否有值。
    • ifPresent(Consume lambda)
      容器若不为空则执行括号中的Lambda表达式。
    • T get()
      获取容器中的元素,若容器为空则抛出NoSuchElement异常。
    • T orElse(T other)
      获取容器中的元素,若容器为空则返回括号中的默认值
  • 相关阅读:
    hdu 2665 划分树
    概率模型与条件随机场
    shell中各种括号的作用()、(())、[]、[[]]、{}
    今日BBC
    小贝_mysql主从复制作用以及案例
    c++ builder 版CreateAnonymousThread用法
    安卓UI适配限定符
    编译3.10内核 出现错误 “undefined reference to....&quot; 解决方法
    iptables的4表5链(未完)
    已有iptables表的查看
  • 原文地址:https://www.cnblogs.com/wuzhilong/p/9434930.html
Copyright © 2020-2023  润新知