jdk都出到16了8还没掌握吗?挽周带你玩转java8新特性(建议收藏)(一)

简介: jdk都出到16了8还没掌握吗?挽周带你玩转java8新特性(建议收藏)

Java 8 新特性

Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本。 Oracle 公司于 2014 年 3 月 18 日发布 Java 8 ,它支持函数式编程,新的 JavaScript 引擎,新的日期 API,新的Stream API 等。

友情链接

菜鸟教程:点我跳转Java8新特性菜鸟教程地址

JDK:点我跳转Jdk8官网下载地址


一.Lambda表达式

Lambda 是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码,将代码像数据一样进行传递。使用它可以写出更简洁,更灵活的代码。作为一种更紧凑的代码风格。使Java的语言表达能力得到了提升。


语法:

(o1,o2) -> Integer.compare(o1,o2);

  • ->:lambda操作符,也叫箭头操作符
  • -> 左边:lambda形参列表 (其实就是接口中的抽象方法的形参列表)
  • -> 右边:lambda体(其实就是重写的抽象方法的方法体)

案例:

  1. 格式:无参数,无返回值
    @Test
    public void test(){
        //原写法
        Runnable runnable=new Runnable() {
            @Override
            public void run() {
                System.out.println("无参无返回值原写法");
            }
        };
        runnable.run();
        //Lambda表达式写法
        Runnable lrunnable =()->{System.out.println("无参无返回值Lambda表达式写法");};
        lrunnable.run();
    }

20210606170920437.png

  1. 格式:Lambda 需要一个参数,但是没有返回值
 @Test
    public void test(){
        //原写法
        Consumer<String> consumer=new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept("需要一个参数没有返回值,原写法");
        //Lambda表达式写法
        Consumer<String> lconsumer =(String s)->{System.out.println(s);};
        lconsumer.accept("需要一个参数没有返回值,Lambda表达式写法");
    }

20210606171317841.png

  1. 格式:数据类型可以省略,因为可由编译器推断得出,称为“类型推断”
    @Test
    public void test(){
        //原写法
        Consumer<String> consumer=new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept("需要一个参数没有返回值,原写法");
        //Lambda表达式写法
        Consumer<String> lconsumer =(s)->{System.out.println(s);};
        lconsumer.accept("需要一个参数没有返回值并且数据类型可以省略, Lambda表达式写法");
    }

20210606171602127.png

  1. 格式:Lambda 若只需要一个参数时,参数的小括号可以省略
    @Test
    public void test(){
        //原写法
        Consumer<String> consumer=new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept("需要一个参数没有返回值,原写法");
        //Lambda表达式写法
        Consumer<String> lconsumer = s ->{System.out.println(s);};
        lconsumer.accept("需要一个参数没有返回值,数据类型可以省略,小括号也可以省略 Lambda表达式写法");
    }

20210606171857461.png

  1. 格式:Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值
    @Test
    public void test(){
        //原写法
        Comparator<Integer> comparator=new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        };
        System.out.println(comparator.compare(1,2));
        //Lambda表达式写法
        Comparator<Integer> lcomparator=(o1,o2)->{return o1.compareTo(o2);};
        System.out.println(lcomparator.compare(1,2));
    }

20210606172358735.png


  1. 格式:当 Lambda 体只有一条语句时, return 与大括号都可以省略
    @Test
    public void test(){
        //原写法
        Comparator<Integer> comparator=new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        };
        System.out.println(comparator.compare(1,2));
        //Lambda表达式写法
        Comparator<Integer> lcomparator=(o1,o2)-> o1.compareTo(o2);
        System.out.println(lcomparator.compare(1,2));
    }

2021060617245052.png

总结:

  • lambda表达式的本质:作为函数式接口的实例
  • -> 左边 : 如果使用泛型,lambda形参列表的参数类型可以省略(类型推断),如果lambda形参列表只有一个参数()也可以省略。
  • -> 右边:lambda体使用一对{}包裹,如果lambda体只有一条执行语句(可能是return语句),可以省略这一对{}return关键字 (如果省略了return关键字{}也一定要去掉)

二.函数式(Funcation)接口

如果一个接口中,只声明了一个抽象方法(可以有多个非抽象方法),则此接口就称为函数式接口,函数式接口可以被隐式转换为 lambda 表达式。

学习之前先来看一下JDK 1.8 之前已有的函数式接口 Runnable

20210606175750829.png

我们常用的一些接口Callable、Runnable、Comparator等在JDK8中都添加了@FunctionalInterface注解。该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上@FunctionInterface,那么编译器会报错。


自定义函数式接口:

/**
 * @author mengzhichao
 * @create 2021-06-06-18:25
 */
@FunctionalInterface
public interface MyInterface {
    void method();
}

总结:在Java8中,Lambda表达式就是一个函数式接口的实例。这就是Lambda表达式和函数式接口的关系。也就是说,只要一个对象是函数式接口的实例。那么该对象就可以用Lambda表达式来表示。所以以前用匿名实现类表示的现在都可以用Lambda表达式来写。


JDK 1.8 新增加的函数接口:

接口 描述
BiConsumer<T,U> 代表了一个接受两个输入参数的操作,并且不返回任何结果
BiFunction<T,U,R> 代表了一个接受两个输入参数的方法,并且返回一个结果
BinaryOperator< T > 代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果
BiPredicate<T,U> 代表了一个两个参数的boolean值方法
BooleanSupplier 代表了boolean值结果的提供方
Consumer 代表了接受一个输入参数并且无返回的操作
DoubleBinaryOperator 代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。
DoubleConsumer 代表一个接受double值参数的操作,并且不返回结果。
DoubleFunction< R > 代表接受一个double值参数的方法,并且返回结果
DoublePredicate 代表一个拥有double值参数的boolean值方法
DoubleSupplier 代表一个double值结构的提供方
DoubleToIntFunction 接受一个double类型输入,返回一个int类型结果。
DoubleToLongFunction 接受一个double类型输入,返回一个long类型结果
DoubleUnaryOperator 接受一个参数同为类型double,返回值类型也为double 。
Function<T,R> 接受一个输入参数,返回一个结果。
IntBinaryOperator 接受两个参数同为类型int,返回值类型也为int 。
IntFunction< R > 接受一个int类型输入参数,返回一个结果 。
IntPredicate 接受一个int输入参数,返回一个布尔值的结果。
IntSupplier 无参数,返回一个int类型结果。
IntToDoubleFunction 接受一个int类型输入,返回一个double类型结果 。
IntToLongFunction 接受一个int类型输入,返回一个long类型结果。
IntUnaryOperator 接受一个参数同为类型int,返回值类型也为int 。
LongBinaryOperator 接受两个参数同为类型long,返回值类型也为long。
LongConsumer 接受一个long类型的输入参数,无返回值。
LongFunction< R > 接受一个long类型输入参数,返回一个结果。
LongPredicate R接受一个long输入参数,返回一个布尔值类型结果。
LongSupplier 无参数,返回一个结果long类型的值。
LongToDoubleFunction 接受一个long类型输入,返回一个double类型结果。


LongToIntFunction 接受一个long类型输入,返回一个int类型结果。
LongUnaryOperator 接受一个参数同为类型long,返回值类型也为long
ObjDoubleConsumer< T > 接受一个object类型和一个double类型的输入参数,无返回值。
ObjIntConsumer< T > 接受一个object类型和一个int类型的输入参数,无返回值。
Predicate< T > 接受一个输入参数,返回一个布尔值结果。
Supplier< T > 无参数,返回一个结果。
ToDoubleBiFunction<T,U> 接受两个输入参数,返回一个double类型结果
ToDoubleFunction< T > 接受一个输入参数,返回一个double类型结果
ToIntBiFunction<T,U> 接受两个输入参数,返回一个int类型结果。
ToIntFunction< T > 接受一个输入参数,返回一个int类型结果。
ToLongBiFunction<T,U> 接受两个输入参数,返回一个long类型结果。
ToLongFunction< T > 接受一个输入参数,返回一个long类型结果。
UnaryOperator< T > 接受一个参数为类型T,返回值类型也为T。

案例(再此只演示极个别常用的,小伙伴们私底下可以自行练习):

  • consumer即消费接口,传入一个参数,并对其进行相应的操作
public class LambdaTest {
    public void happyTime(double money,Consumer<Double> consumer){
        consumer.accept(money);
    }
    @Test
    public void test(){
        //原写法
       happyTime(500, new Consumer<Double>() {
           @Override
           public void accept(Double aDouble) {
               System.out.println("原写法,价格为:"+aDouble);
           }
       });
        //Lambda表达式写法
        happyTime(500,money-> System.out.println("Lambda表达式写法,价格为:"+money));
    }
}

2021060618434467.png

  • supplier即供给接口,可以传入数据,作为一个容器;
public class LambdaTest {
    @Test
    public void test(){
        //原写法
        Supplier<String> supplier=new Supplier<String>() {
            @Override
            public String get() {
                return "原写法,供给型接口";
            }
        };
        System.out.println(supplier.get());
        //Lambda表达式写法
        Supplier<String> lSupplier=()->"lambda写法,供给型接口";
        System.out.println(lSupplier.get());
    }
}

20210606231915280.png

  • function即方法接口,主要是用作数据类型之间的转换;
public class LambdaTest {
    @Test
    public void test(){
        //原写法(给一个int 转成字符串并返回)
        Function<Integer,String> function=new Function<Integer, String>() {
            @Override
            public String apply(Integer integer) {
                return String.valueOf(integer);
            }
        };
        System.out.println(function.apply(10).getClass().getName());
        //Lambda表达式写法
        Function<Integer,String> lFunction=(integer) -> String.valueOf(integer);
        System.out.println(lFunction.apply(20).getClass().getName());
    }
}

20210606232435222.png

  • predicate即判断接口,传入参数,而后返回判断的结果true/false;
public class LambdaTest {
    //根据给定的规则,过滤集合中的字符串。此规则由Predicate的方法决定
    public List<String> filterString(List<String> list, Predicate<String> predicate){
        List<String> filterList=new ArrayList<>();
        for (String s:list){
            if (predicate.test(s)){
                filterList.add(s);
            }
        }
        return filterList;
    }
    @Test
    public void test(){
        //原写法
        List<String> list=Arrays.asList(new String[]{"上海", "香港", "澳门", "曹县"});
        List<String> filterString = filterString(list, new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return "曹县".equals(s) ? true : false;
            }
        });
        System.out.println(filterString);
        //Lambda表达式写法
        List<String> lfilterString = filterString(list, s -> "上海".equals(s) ? true : false);
        System.out.println(lfilterString);
    }
}

20210606185721575.png

相关文章
|
3天前
|
存储 算法 Java
Java Set因其“无重复”特性在集合框架中独树一帜
【10月更文挑战第14天】Java Set因其“无重复”特性在集合框架中独树一帜。本文深入解析Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定的数据结构(哈希表、红黑树)确保元素唯一性,并提供最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的`hashCode()`与`equals()`方法。
14 3
|
7天前
|
安全 Java API
Java 17新特性让你的代码起飞!
【10月更文挑战第4天】自Java 8发布以来,Java语言经历了多次重大更新,每一次都引入了令人兴奋的新特性,极大地提升了开发效率和代码质量。本文将带你从Java 8一路走到Java 17,探索那些能让你的代码起飞的关键特性。
32 1
|
1天前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
9 3
|
4天前
|
Java 开发者
在Java的集合世界里,Set以其独特的特性脱颖而出,它通过“哈希魔法”和“红黑树防御”两大绝技
【10月更文挑战第13天】在Java的集合世界里,Set以其独特的特性脱颖而出。它通过“哈希魔法”和“红黑树防御”两大绝技,有效抵御重复元素的侵扰,确保集合的纯洁性和有序性。无论是“人海战术”还是“偷梁换柱”,Set都能从容应对,成为开发者手中不可或缺的利器。
19 6
|
1天前
|
存储 Java 数据处理
Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位
【10月更文挑战第16天】Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位。本文通过快速去重和高效查找两个案例,展示了Set如何简化数据处理流程,提升代码效率。使用HashSet可轻松实现数据去重,而contains方法则提供了快速查找的功能,彰显了Set在处理大量数据时的优势。
7 2
|
1天前
|
Java 开发者
在Java集合世界中,Set以其独特的特性脱颖而出,专门应对重复元素
在Java集合世界中,Set以其独特的特性脱颖而出,专门应对重复元素。通过哈希表和红黑树两种模式,Set能够高效地识别并拒绝重复元素的入侵,确保集合的纯净。无论是HashSet还是TreeSet,都能在不同的场景下发挥出色的表现,成为开发者手中的利器。
11 2
|
1天前
|
Java
Java Set以其“不重复”的特性,为我们提供了一个高效、简洁的处理唯一性约束数据的方式。
【10月更文挑战第16天】在Java编程中,Set接口确保集合中没有重复元素,每个元素都是独一无二的。HashSet基于哈希表实现,提供高效的添加、删除和查找操作;TreeSet则基于红黑树实现,不仅去重还能自动排序。通过这两个实现类,我们可以轻松处理需要唯一性约束的数据,提升代码质量和效率。
9 2
|
3天前
|
存储 Java 数据处理
在Java集合框架中,Set接口以其独特的“不重复”特性脱颖而出
【10月更文挑战第14天】在Java集合框架中,Set接口以其独特的“不重复”特性脱颖而出。本文通过两个案例展示了Set的实用性和高效性:快速去重和高效查找。通过将列表转换为HashSet,可以轻松实现去重;而Set的contains方法则提供了快速的元素查找功能。这些特性使Set成为处理大量数据时的利器。
12 4
|
4天前
|
存储 Java 数据处理
Java中的Set接口以其独特的“不重复”特性,在集合框架中占据重要地位。
【10月更文挑战第13天】Java中的Set接口以其独特的“不重复”特性,在集合框架中占据重要地位。本文通过两个案例展示了Set的实用性和高效性:快速去重和高效查找。通过将列表转换为HashSet,可以轻松实现去重;而Set的contains方法则提供了高效的元素查找功能。这些特性使Set在处理大量数据时表现出色,值得我们在日常编程中充分利用。
18 3
|
7天前
|
Java 编译器 API
从Java 8到Java 17,这些新特性让你的代码起飞!
【10月更文挑战第10天】在软件开发领域,Java作为一种历史悠久且广泛使用的编程语言,不断进化以适应新的需求和挑战。从Java 8到Java 17,每一次版本更新都带来了诸多新特性和改进,极大地提升了开发效率和代码质量。今天,我们就来一起探讨这些新特性,看看它们是如何让我们的代码“起飞”的。
72 0