栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JDK1.8新特性

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JDK1.8新特性

目录

1.Lambda表达式

1.1 概念

1.2 语法

1.3 代码分析

1.3.1 无参无返回值

1.3.2 有参有返回值

1.3.3 lambda表达式注意事项

2.函数式接口

2.1 内置函数式接口

2.2 Consumer

2.3 Supplier供给型函数式接口

2.4 Function 函数型函数式接口,r>

2.5 Predicated

3.方法引用

3.1 什么是方法引用

3.2 对象::实例方法

3.3 类名::静态方法

3.4 类名::实例方法

3.5 类名::new 引用类的构造器

3.6 类型[]::new


1.Lambda表达式

1.1 概念

(1)Lambda表达式:特殊的匿名内部类,语法更简洁。

(2)Lambda表达式允许把函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递。

1.2 语法

基本语法

        <函数式接口>  <变量名>=(参数1,参数2...)->{

                                //方法体

        };

注意: 函数式接口:接口中只有一个抽象方法。

(参数1,参数2): 抽象方法的参数

->: 分隔符

{}:表示抽象方法的实现

1.3 代码分析
  • Thread 类需要 Runnable 接口作为参数,其中的抽象 run 方法是用来指定线程任务内容的核心

  • 为了指定 run 的方法体,不得不需要 Runnable 接口的实现类

  • 为了省去定义一个 Runnable 实现类的麻烦,不得不使用匿名内部类

  • 必须覆盖重写抽象 run 方法,所以方法名称、方法参数、方法返回值不得不再写一遍,且不能写错

  • 而实际上,似乎只有方法体才是关键所在。

        这时可以使用lambda表示完成上面的要求。  

        前提:必须是函数式接口。

        简化匿名内部类的使用,语法更加简单。

总代码展示:

public class LambdaTest {
    public static void main(String[] args) {
        My m=new My();
        Thread t1=new Thread(m);
        t1.start();

        Thread t2=new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("匿名函数式");
            }
        });
        t2.start();

        Runnable t3=()->{
            System.out.println("lambda表达式");
        };
        Thread t03=new Thread(t3);
        t03.start();

        Thread t4=new Thread(()->{
            System.out.println("lambda精简表达式");
        });
        t4.start();
    }
}
class My implements Runnable{

    @Override
    public void run() {
        System.out.println("Runnable方法");
    }
}

1.3.1 无参无返回值

代码展示:

public class WuCanWuFan {
    public static void main(String[] args) {
        Swimming swimming=new Swimming() {
            @Override
            public void swim() {
                System.out.println("小明在游泳");
            }
        };
        fun(swimming);

        System.out.println("================lambda=========================");

//        Swimming swimming1=()->{
//            System.out.println("小花在游泳");
//        };
        fun(()->{
            System.out.println("小花在游泳");
        });
    }

    public static void fun(Swimming swimming){
        swimming.swim();
    }
}
interface Swimming{
    public void swim();
}

1.3.2 有参有返回值

举例演示 java.util.Comparator 接口的使用场景代码,其中的抽象方法定义为:

  • public abstract int compare(T o1, T o2);

当需要对一个对象集合进行排序时, Collections.sort 方法需要一个 Comparator 接口实例来指定排序的规则。

代码展示:

public class Compable {
    public static void main(String[] args) {
        List people=new ArrayList<>();
        people.add(new Person("张三",15,185));
        people.add(new Person("李四",23,179));
        people.add(new Person("王五",8,145));
        people.add(new Person("赵六",34,180));

        //对集合中的元素进行排序 按照年龄从小到大
        //传统做法:Comparator:排序规则接口
        Comparator comparator=new Comparator() {
            //int : 0表示新加的元素和集合中的元素是相等的
            //1表示新加的元素比集合中的元素大
            //-1表示新加的元素比集合中的元素小
            @Override
            public int compare(Person o1, Person o2) {
                return o2.getAge()- o1.getAge();
            }
        };
        Collections.sort(people,comparator);
        for (Person p:people) {
            System.out.println(p);
        }

        System.out.println("===============================lambda===============================");

        Comparator comparator1=(Person o1,Person o2)->{
            return o1.getAge()- o2.getAge();
        };

        Collections.sort(people,comparator1);
        for (Person p:people) {
            System.out.println(p);
        }

    }
}
class Person{
    private String name;

    private Integer age;

    private Integer tall;

    public Person() {
    }

    public Person(String name, Integer age, Integer tall) {
        this.name = name;
        this.age = age;
        this.tall = tall;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getTall() {
        return tall;
    }

    public void setTall(Integer tall) {
        this.tall = tall;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + ''' +
                ", age=" + age +
                ", tall=" + tall +
                '}';
    }
}

1.3.3 lambda表达式注意事项

注意事项 :

        形参列表的数据类型会自动推断

        如果形参列表为空,只需保留()

        若形参只有一个,()可以省略,只需要参数的名称即可(此题证明)

        如果执行语句只有一句,且无返回值,{}可以省略,若有返回值,则想省去{},则必须同时省略return,且执行语句也保证只有一句

        Lambda不会生成一个单独的内部类文件

public class NoticeTest {
    public static void main(String[] args) {

        fun(n->{
            System.out.println(n+"正在玩手机");
        });
    }

    public static void fun(Plays plays){
        plays.play("小明");
    }
}
interface Plays{
    public void play(String name);
}

2.函数式接口

        我们知道使用Lambda表达式的前提是需要有函数式接口。而Lambda使用时不关心接口名,抽象方法名,只关心抽 象方法的参数列表和返回值类型。因此为了让我们使用Lambda方便,JDK提供了大量常用的函数式接口。

        常见的函数式接口:java.util.function保存

2.1 内置函数式接口

        如果一个接口只有一个抽象方法,则该接口称之为函数式接口,函数式接口可以使用Lambda表达式,Lambdda表达式会被匹配到这个抽象方法上。

        @Functionallnterface注解检测接口是否符合函数式接口。

public class Test03 {

    public static void main(String[] args) {
        Operater o=arr -> {
             int sum=0;
             for(int n:arr){
                 sum+=n;
             }
            System.out.println("数组的和为:"+sum);
        };

        fun(o);
    }

    public static void fun(Operater operater){
         int[] arr={2,3,4,5,6,7,11};
         operater.getSum(arr);
    }

}
@FunctionalInterface
interface Operater{
    //求数组的和
    public abstract void getSum(int[] arr);
}

2.2 Consumer

消费型函数 :有参无返回值

举例:去美甲店消费一次的开销

public class ConsumerTest {
    public static void main(String[] args) {

        Consumer consumer=t->{
            System.out.println("美甲花了:"+t);
        };
        fun(consumer,200);

    }
    //调用某个方法时,该方法需要的参数为接口类型,这时就应该能想到使用lambda
    public static void fun(Consumer consumer, double money){
        consumer.accept(money);
    }
}

举例:遍历数组和

public class ConsumerTest02 {
    public static void main(String[] args) {
        getSum(t->{
            int sum=0;
            for (int i:t) {//此处遍历t即代表arr
                sum+=i;
            }
            System.out.println(sum);
        },new int[]{1,2,3,4,5});
    }
    public static void getSum(Consumer consumer, int[] arr){//注意Consumer
         consumer.accept(arr);

    }
}

2.3 Supplier供给型函数式接口

T表示返回结果的泛型 :无参有返回值的函数式接口

举例:随机获取0到10之间的数字

public class SupplierTest {
    public static void main(String[] args) {
        getNumber(()->{
            return new Random().nextInt(10);
        });
    }
    public static void getNumber(Supplier supplier){
        Integer integer = supplier.get();
        System.out.println("获取数字为:"+integer);
    }
}

2.4 Function 函数型函数式接口

有参,有返回值

T:参数类型的泛型

R:函数返回结果的泛型

举例:将字符串转大写

public class FunctionTest {
    public static void main(String[] args) {

        getUpper(t->{
            return t.toUpperCase(Locale.ROOT);//所传参数随便写
        },"hello world");
    }
    public static void getUpper(Function function,String str){
        String apply = function.apply(str);
        System.out.println("结果为:·"+apply);
    }
}

举例:计算字符串长度

public class FunctionTest02 {
    public static void main(String[] args) {
        getLength(t->{
            return t.replace(" ","").length();
        },"hello world");
    }
    public static void getLength(Function function,String str){
        Integer apply = function.apply(str);
        System.out.println("长度为:"+apply);
    }
}

2.5 Predicated

boolean test(T t);确定类型为T的对象是否满足条件,并返回boolean类型

举例:判断名字是否过长

public class PredicateTest {
    public static void main(String[] args) {

        getNameLength(t->{
            return t.length()>3?true:false;
        },"迪丽热巴.迪力木拉提");
    }
    public static void getNameLength(Predicate predicate,String name){
        boolean test = predicate.test(name);
        System.out.println("名字长度是否超过3:"+test);
    }
}

3.方法引用

        如果我们在Lambda中所指定的功能,已经有其他方法存在相同方案,那是否还有必要再写重复逻辑?可以直接“引 用”过来就好了---方法引用

        请注意其中的双冒号 :: 写法,这被称为“方法引用”,是一种新的语法

举例:计算数组和

public class PullIn {
    public static void getSum(int[] arr){
        int sum=0;
        for (Integer i:arr) {
            sum+=i;
        }
        System.out.println("数组和为:"+sum);
    }
    public static void sum(Consumer consumer){
        int[] arr={1, 2, 3, 4, 5};
        consumer.accept(arr);
    }

    public static void main(String[] args) {
        //此处与上述getSum方法一模一样,造成冗余
//        sum(arr->{
//            int sum=0;
//            for (Integer i:arr) {
//                sum+=i;
//            }
//            System.out.println("数组和为:"+sum);
//        },new int[]{1, 2, 3, 4, 5});
        sum(PullIn::getSum);
    }
}

3.1 什么是方法引用

        方法引用是Lambda表达式的一种简写形式。如果Lambda表达式方法体只是调用一个特定的已经存在的方法,则可以使用方法引用。

        常见形式:

        (1)对象::方法名

        (2)类名::静态方法

        (3)类名::普通方法

        (4)类名::new 调用的构造器

        (5)String[]::new 调用数组的构造器

3.2 对象::实例方法

注意:

1.被引用的方法,参数要和接口中的抽象方法的参数一样

2.当接口抽象方法有返回值时,被引用的方法也必须有返回值

举例:获取当前时间

public class PullInTest01 {
    //对象::实例方法
    public static void main(String[] args) {
        Date d=new Date();
//        Supplier time=()->{
//            return d.getTime();
//        };
        //使用方法引用
        Supplier time=d::getTime;
        //注意:
        //1.被引用的方法,参数要和接口中的抽象方法的参数一样
        //2.当接口抽象方法有返回值时,被引用的方法也必须有返回值

        Long aLong = time.get();
        System.out.println("aLong = "+aLong);
    }
}

3.3 类名::静态方法

举例:获取当前时间

public class PullInTest02 {
    //类名::静态方法
    public static void main(String[] args) {
//        Supplier su=()->{
//            return System.currentTimeMillis();
//        };
        Supplier su=System::currentTimeMillis;

        Long aLong = su.get();
        System.out.println("aLong="+aLong);
    }
}

3.4 类名::实例方法

(注意:类名::实例方法实际上会将第一个参数作为方法的调用者)

举例:字符串长度及截取字符串

public class PullInTest03 {
    public static void main(String[] args) {
        //类名::实例方法(注意:类名::实例方法实际上会将第一个参数作为方法的调用者)
//        Function f1=(String str)->{
//            return str.length();
//        };
        Function f1=String::length;

        Integer hello = f1.apply("hello");
        System.out.println("字符串长度为:"+hello);

        //BiFunction f2=String::substring;
        //相当于这样的Lambda
        BiFunction f2=(String str,Integer index)->{
            return str.substring(index);
        };
        String helloworld = f2.apply("helloworld", 3);
        System.out.println(helloworld);
    }


}

3.5 类名::new 引用类的构造器

举例:person介绍

Person类

public class Person {
    private String name;

    private Integer age;

    public Person() {
        System.out.println("调用无参构造");
    }

    public Person(String name, Integer age) {
        System.out.println("调用有参构造"+name+"---"+age);
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

测试类

public class PullTest04 {
    //类名::new 引用类的构造器
    public static void main(String[] args) {
//        Supplier su=()->{
//            return new Person();
//        };
        Supplier su=Person::new;
        Person person = su.get();
        System.out.println(person);

//        BiFunction bif=(String name,Integer age)->{
//            return new Person(name,age);
//        };
        BiFunction bif=Person::new;
        Person name = bif.apply("小明", 18);
        System.out.println(name);
    }
}

3.6 类型[]::new

举例:数组存放

public class PullInTest05 {
    //类型【】::new
    public static void main(String[] args) {

//        Function f1=(Integer length)->{
//            return new int[length];
//        };
        Function f1=int[]::new;
        int[] apply = f1.apply(10);
        System.out.println(Arrays.toString(apply));
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1020111.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号