Java8新特性 -- Lambda表达式

Java8新特性 – Lambda表达式

1. 什么是Lambda表达式?

Lambda是一个匿名函数,可以理解为是一段可以传递的代码,可以将代码像传递参数、传递数据一样进行传输。使用Lambda表达式,可以写出更加紧凑、更加简洁、更加灵活的代码。

2. 使用Lambda表达式的限制条件?

Lambda并不是任何地方都可以使用,Lambda表达式需要“函数式接口”的支持。

3. 什么是函数式接口?

接口中只有一个抽象方法的接口,称为函数式接口,可以用@FunctionalInterface修饰一下,这里需要注意的是:未使用 @FunctionalInterfaces注解的接口未必就不是函数式接口,一个接口是不是函数式接口的条件只有一条,即接口中只有一个抽象方法的接口(Object类中的方法不算)。而使用@FunctionalInterface注解修饰了的接口就一定是函数式接口,添加@FunctionalInterface注解可以帮助我们检查是否是函数式接口。

4. Lambda使用

​ 我们这里给定四个简单的接口,用过这四个接口来简单了解下lambda表达式的使用。

// 无参无返回值类型
@FunctionalInterface
public interface NoParamNoReturn {
    public void method();
}

// 无参有返回值类型
@FunctionalInterface
public interface ReturnNoParam {
    public String method();
}

// 有参无返回值类型
@FunctionalInterface
public interface ParamNoReturn {
    public void method(String name);
}

// 有参有返回值类型
@FunctionalInterface
public interface ParamReturn {
    public String method(String name);
}

语法形式为 () -> {},其中 () 用来描述参数列表,{} 用来描述方法体,-> 为 lambda运算符 ,读作(goes to)。

首先我们举个简单例子:

  • 1. 无参无返回值类型Lambda表达式
// 首先我们不使用Lambda表达式来实现: 打印"hello world"
NoParamNoReturn noParamNoReturn = new NoParamNoReturn() {
    @Override
    public void method() {
        System.out.println("hello world");
    }
};
noParamNoReturn.method(); // 执行该方法
// 我们再使用Lambda表达式来简化上面代码
// 从new开始到方法名全部删除,保留括号,使用'->'指向方法体,当方法体只有一行时,也可删除大括号。
NoParamNoReturn noParamNoReturn = () -> System.out.println("hello world");
noParamNoReturn.method(); // 执行该方法
  • 2. 无参有返回值类型Lambda表达式
// 首先我们不使用Lambda表达式来实现: 返回"hello world"
ReturnNoParam returnNoParam = new ReturnNoParam() {
    @Override
    public String method() {
        return "hello world";
    }
};
String s = returnNoParam.method(); // 执行该方法
// 我们再使用Lambda表达式来简化上面代码
// 从new开始到方法名全部删除,保留括号,使用'->'指向方法体,当方法体只有一行时,也可删除大括号。
// 最后删掉return,保留返回值。
ReturnNoParam returnNoParam = () -> "hello world";
String s = returnNoParam.method(); // 执行该方法
  • 3. 有参无返回值类型Lambda表达式
// 首先我们不使用Lambda表达式来实现: 打印参数
ParamNoReturn paramNoReturn = new ParamNoReturn() {
    @Override
    public String method(String s) {
        System.out.println(s);
    }
};
paramNoReturn.method("hello world"); // 执行该方法
// 我们再使用Lambda表达式来简化上面代码
// 从new开始到方法名全部删除,若只有一个参数,则删除括号;若有多个参数,则保留括号(a,b)。使用'->'指向方法体,当方法体只有一行时,也可删除大括号。
ParamNoReturn paramNoReturn = s -> System.out.println(s);
paramNoReturn.method("hello world"); // 执行该方法
  • 4. 有参有返回值类型Lambda表达式
// 首先我们不使用Lambda表达式来实现: 返回传入的参数
ParamReturn paramReturn = new ParamReturn() {
    @Override
    public String method(String s) {
        return s;
    }
};
String s = paramReturn.method("hello world"); // 执行该方法
// 我们再使用Lambda表达式来简化上面代码
// 从new开始到方法名全部删除,若只有一个参数,则删除括号;若有多个参数,则保留括号(a,b)。使用'->'指向方法体,当方法体只有一行时,也可删除大括号。
// 最后删掉return,保留返回值。
ParamReturn paramReturn = s -> s;
String s = paramNoReturn.method("hello world"); // 执行该方法

​ 我们可以自定以函数式接口实现我们想要的功能,但是有些功能很简单(例如上面的举例),但依然要定义函数式接口,这就显得比较臃肿。**因此, JDK提供了大量常用的函数式接口以丰富Lambda的典型使用场景,它们主要在 java.util.function 包中被提供。 下面是简单的几个接口及使用示例。 **

  • 消费型(consumer) : Consumer接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据,其数据类型由泛型决定。Consumer接口中包含抽象方法void accept(T t),意为消费一个指定泛型的数据。
  • 判定型(predicate) : Predicate接口 作用:对某种数据类型的数据进行判断,结果返回一个boolean值 。 boolean test(T t):用来对指定数据类型数据进行判断的方法。 结果: 符合条件,返回true。不符合条件,返回false 。
  • 函数型(function) : Function<T,R>接口用来根据一个类型的数据得到另一个类型的数据, 前者称为前置条件,后者称为后置条件。Function接口中最主要的抽象方法为:R apply(T t),根据类型T的参数获取类型R的结果。 使用的场景例如:将String类型转换为Integer类型。
  • 供给型(supplier) : Supplier接口仅包含一个无参的方法:T get()。用来获取一个泛型参数指定类型的对象数据。 Supplier接口被称之为生产型接口,指定接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据 。

下面时分别对着四个函数型接口举例:

// 消费型(consumer)案例 : 模拟购物
public static void main(String[] args) {
    buy(5.00,money -> System.out.println("我花了" + money + "元"));
}

public static void buy(Double money, Consumer<Double> consumer){
    consumer.accept(money);
}
// 判定型(predicate)案例 : 筛选字符串大于5的
public static void main(String[] args) {
    List<String> list = Arrays.asList("dfgsfgsdfg","fgsfg","ff","fgs");

    List<String> strings = filterString(list, s -> s.length() > 5);
    System.out.println(strings.toString());

}

public static List<String> filterString(List<String> stringList, Predicate<String> predicate){
    List<String> list = new ArrayList<>();
    for(String s : stringList){
        if(predicate.test(s)){
            list.add(s);
        }
    }
    return list;
}
// 函数型(function)案例 : 将list转为map
public static void main(String[] args) {
    List<String> list = Arrays.asList("a","b","c","d");
    Map<Integer, String> map = listToMap(list, stringList -> stringList.stream().collect(Collectors.toMap(String::hashCode, string -> string)));
    System.out.println(map.toString());

}

public static Map<Integer,String> listToMap(List<String> stringList, Function<List<String>,Map<Integer,String>> function){
    return function.apply(stringList);
}
// 供给型(supplier)案例 : 获奖
public static void main(String[] args) {

    Random random = new Random();

    Double money = getMoney(() -> random.nextDouble());
    System.out.println(money);
}

public static Double getMoney(Supplier<Double> supplier){
    return supplier.get();
}
发布了15 篇原创文章 · 获赞 1 · 访问量 3124

猜你喜欢

转载自blog.csdn.net/ZeroWdd/article/details/104349655