Java8新特性之Lambda

简介: Java8新特性之Lambda

接口的默认方法



1.Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法


interface Formula {
    double calculate(int a);
    default double sqrt(int a) {
      return Math.sqrt(a);
    }
} 


2.例子: Formula接口在拥有calculate方法之外同时还定义了sqrt方法,实现了Formula接口的子类只需要实现一个calculate方法,默认方法sqrt将在子类上可以直接使用


Formula formula = new Formula() {
    @Override
    public double calculate(int a) {
      return sqrt(a * 100);
    }
};
formula.calculate(100); // 100.0
formula.sqrt(16); // 4.0


Lambda 表达式:



1.第一种:


Collections.sort(names, (String a, String b) -> {
  return b.compareTo(a);
});


2.第二种: 对于函数体只有一行代码的,你可以去掉大括号{}以及return关键字


Collections.sort(names, (String a, String b) -> b.compareTo(a)


3.第三种: Java编译器可以自动推导出参数类型,所以你可以不用再写一次类型


Collections.sort(names, (a, b) -> b.compareTo(a)


函数式接口



每一个lambda表达式都对应一个类型,通常是接口类型。而***函数式接口*是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。因为默认方法不算抽象方法,所以你也可以给你的函数式接口添加默认方法。


可以将lambda表达式当作任意只包含一个抽象方法的接口类型,确保你的接口一定达到这个要求,你只需要给你的接口添加 @FunctionalInterface 注解,编译器如果发现你标注了这个注解的接口有多于一个抽象方法的时候会报错的。


@FunctionalInterface
interface Converter<F, T> {
  T convert(F from);
}
Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
Integer converted = converter.convert("123");
System.out.println(converted); // 123


方法与构造函数引用:



1.Java 8 允许你使用::关键字来传递方法或者构造函数引用


Converter<String, Integer> converter = Integer::valueOf;
Integer converted = converter.convert("123");
System.out.println(converted); // 123



2.引用一个对象的方法:


converter = something::startsWith;
String converted = converter.convert("Java");
System.out.println(converted); // "J"


3.接下来看看构造函数是如何使用::关键字来引用的,首先我们定义一个包含多个构造函数的简单类


class Person {
    String firstName;
    String lastName;
    Person() {}
    Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}
//指定一个用来创建Person对象的对象工厂接口
interface PersonFactory<P extends Person> {
  P create(String firstName, String lastName);
}
//使用例子
//只需要使用 Person::new 来获取Person类构造函数的引用,Java编译器会自动根据PersonFactory.create方法的签名来选择合适的构造函数
PersonFactory<Person> personFactory = Person::new;
Person person = personFactory.create("Peter", "Parker");


Lambda 作用域:



  1. 在lambda表达式中访问外层作用域和老版本的匿名对象中的方式很相似。你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量


  1. 访问局部变量:


final int num = 1;
Converter<Integer, String> stringConverter = (from) -> String.valueOf(from + num);  
stringConverter.convert(2); // 3
//但是和匿名对象不同的是,这里的变量num可以不用声明为final,该代码同样正确:
nt num = 1;
Converter<Integer, String> stringConverter = (from) -> String.valueOf(from + num);
stringConverter.convert(2); // 3
//不过这里的num必须不可被后面的代码修改(即隐性的具有final的语义),例如下面的就无法编译:在lambda表达式中试图修改num同样是不允许的。
int num = 1;
Converter<Integer, String> stringConverter = (from) -> String.valueOf(from + num);
num = 3;


3.访问对象字段与静态变量: 和本地变量不同的是,lambda内部对于实例的字段以及静态变量是即可读又可写。该行为和匿名对象是一致的:


class Lambda4 {
    static int outerStaticNum;
    int outerNum;
    void testScopes() {
        Converter<Integer, String> stringConverter1 = (from) -> {
            outerNum = 23;
            return String.valueOf(from);
        };
        Converter<Integer, String> stringConverter2 = (from) -> {
            outerStaticNum = 72;
            return String.valueOf(from);
        };
    }
}


4.访问接口的默认方法: 还记得之前的formula例子么,接口Formula定义了一个默认方法sqrt可以直接被formula的实例包括匿名对象访问到,但是在lambda表达式中这个是不行的。Lambda表达式中是无法访问到默认方法的,以下代码将无法编译:


Formula formula = (a) -> sqrt( a * 100);


新接口介绍:



1.Predicate接口: 只有一个参数,返回boolean类型。该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非)


Predicate<String> predicate = (s) -> s.length() > 0;
predicate.test("foo");
// true
predicate.negate().test("foo"); // false
Predicate<Boolean> nonNull = Objects::nonNull;
Predicate<Boolean> isNull = Objects::isNull;
Predicate<String> isEmpty = String::isEmpty;
Predicate<String> isNotEmpty = isEmpty.negate();


2.Function 接口: 有一个参数并且返回一个结果,并附带了一些可以和其他函数组合的默认方法(compose, andThen):


Function<String, Integer> toInteger = Integer::valueOf;
Function<String, String> backToString = toInteger.andThen(String::valueOf);
backToString.apply("123"); // "123"


3.Supplier 接口: 返回一个任意范型的值,和Function接口不同的是该接口没有任何参数


Supplier<Person> personSupplier = Person::new;
personSupplier.get(); // new Person


4.Comparator 接口: Comparator 是老Java中的经典接口, Java 8在此之上添加了多种默认方


Comparator<Person> comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName);
Person p1 = new Person("John", "Doe");
Person p2 = new Person("Alice", "Wonderland");
comparator.compare(p1, p2); // > 0
comparator.reversed().compare(p1, p2); // < 0


5.Optional 接口:


(1)Optional 不是函数是接口,这是个用来防止NullPointerException异常的辅助类型,这是下一节中将要用到的重要概念,现在先简单的看看这个接口能干什么:


(2)Optional 被定义为一个简单的容器,其值可能是null或者不是null。在Java 8之前一般某个函数应该返回非空对象但是偶尔却可能返回了null,而在Java 8中,不推荐你返回null而是返回Optional。


Optional<String> optional = Optional.of("bam");
optional.isPresent(); // true
optional.get(); // "bam"
optional.orElse("fallback"); // "bam"
optional.ifPresent((s) -> System.out.println(s.charAt(0))); // "b"
目录
相关文章
|
4天前
|
SQL Rust Java
怎么理解Java中的lambda表达式
Lambda表达式是JDK8引入的新语法,用于简化匿名内部类的代码写法。其格式为`(参数列表) -&gt; { 方法体 }`,适用于函数式接口(仅含一个抽象方法的接口)。通过Lambda表达式,代码更简洁灵活,提升Java的表达能力。
|
8天前
|
缓存 运维 Java
Java静态代码块深度剖析:机制、特性与最佳实践
在Java中,静态代码块(或称静态初始化块)是指类中定义的一个或多个`static { ... }`结构。其主要功能在于初始化类级别的数据,例如静态变量的初始化或执行仅需运行一次的初始化逻辑。
25 4
|
3月前
|
存储 Java 开发者
什么是java的Compact Strings特性,什么情况下使用
Java 9引入了紧凑字符串特性,优化了字符串的内存使用。它通过将字符串从UTF-16字符数组改为字节数组存储,根据内容选择更节省内存的编码方式,通常能节省10%至15%的内存。
|
3月前
|
安全 Java API
Java中的Lambda表达式:简化代码的现代魔法
在Java 8的发布中,Lambda表达式的引入无疑是一场编程范式的革命。它不仅让代码变得更加简洁,还使得函数式编程在Java中成为可能。本文将深入探讨Lambda表达式如何改变我们编写和维护Java代码的方式,以及它是如何提升我们编码效率的。
|
3月前
|
存储 Java 数据挖掘
Java 8 新特性之 Stream API:函数式编程风格的数据处理范式
Java 8 引入的 Stream API 提供了一种新的数据处理方式,支持函数式编程风格,能够高效、简洁地处理集合数据,实现过滤、映射、聚合等操作。
120 6
|
3月前
|
Java API 开发者
Java中的Lambda表达式与Stream API的协同作用
在本文中,我们将探讨Java 8引入的Lambda表达式和Stream API如何改变我们处理集合和数组的方式。Lambda表达式提供了一种简洁的方法来表达代码块,而Stream API则允许我们对数据流进行高级操作,如过滤、映射和归约。通过结合使用这两种技术,我们可以以声明式的方式编写更简洁、更易于理解和维护的代码。本文将介绍Lambda表达式和Stream API的基本概念,并通过示例展示它们在实际项目中的应用。
|
4月前
|
安全 Java API
Java中的Lambda表达式与Stream API的高效结合####
探索Java编程中Lambda表达式与Stream API如何携手并进,提升数据处理效率,实现代码简洁性与功能性的双重飞跃。 ####
51 0
|
4月前
|
Java API 开发者
Java中的Lambda表达式:简洁代码的利器####
本文探讨了Java中Lambda表达式的概念、用途及其在简化代码和提高开发效率方面的显著作用。通过具体实例,展示了Lambda表达式如何在Java 8及更高版本中替代传统的匿名内部类,使代码更加简洁易读。文章还简要介绍了Lambda表达式的语法和常见用法,帮助开发者更好地理解和应用这一强大的工具。 ####
|
4月前
|
并行计算 Java 编译器
深入理解Java中的Lambda表达式
在Java 8中引入的Lambda表达式,不仅简化了代码编写,还提升了代码可读性。本文将带你探索Lambda表达式背后的逻辑与原理,通过实例展示如何高效利用这一特性优化你的程序。
|
4月前
|
搜索推荐 Java API
探索Java中的Lambda表达式
本文将深入探讨Java 8引入的Lambda表达式,这一特性极大地简化了代码编写,提高了程序的可读性。通过实例分析,我们将了解Lambda表达式的基本概念、使用场景以及如何优雅地重构传统代码。文章不仅适合初学者,也能帮助有经验的开发者加深对Lambda表达式的理解。