Jdk8特性lambda


在这里插入图片描述
在这里插入图片描述
在java的历史中,java8的变化举重若轻

1、让方法参数具备行为能力

1.1、找绿色的苹果

在这里插入图片描述
其中apple类是一个实体类它有颜色、重量等属性
上面的例子是遍历参数中的apple集合找到颜色为绿色的苹果
用下面的这个方法创建出需要的apple集合

List<Apple> list = Arrays.asList(new Apple("green", 150), new Apple("yellow", 120), new Apple("green", 170));

1.2、找红色的苹果

最初级的办法就是另外再写一个方法。

高级一点的就是在上面方法上加一个参数为我们需要找的颜色

在这里插入图片描述

1.3、根据颜色又根据重量去查找

1.3.1、策略模式的应用,方法参数具备了行为

这种仓促的变化代表着需求的不断变化,对于我们写程序的来说如何让调用者察觉不到这种变化?

public class FilterApple {
   定义一个接口作为作为方法的参数,具体的业务算法作为他的实现类
    public interface AppleFilter {
        boolean filter(Apple apple);
    }
    public static List<Apple> findApple(List<Apple> apples, AppleFilter appleFilter) {
        List<Apple> list = new ArrayList<>();
        for (Apple apple : apples) {
            if (appleFilter.filter(apple))
                list.add(apple);
        }
        return list;
    }
    实现我们定义的接口,写我们的业务逻辑
    public static class GreenAnd160WeightFilter implements AppleFilter {
        @Override
        public boolean filter(Apple apple) {
            return (apple.getColor().equals("green") && apple.getWeight() >= 160);
        }
    }
     public static void main(String[] args) throws InterruptedException {
         List<Apple> list = Arrays.asList(new Apple("green", 150), new Apple("yellow", 120), new Apple("green", 170));
         List<Apple> result = findApple(list, new GreenAnd160WeightFilter());
        System.out.println(result);、
     }
   }

1.3.2、直接使用匿名内部类来调用

对于上一节的策略模式,如果我们每一个业务逻辑都要写一个filter来实现这个业务的具体算法,是很麻烦的

 List<Apple> yellowList = findApple(list, new AppleFilter() {
            @Override
            public boolean filter(Apple apple) {
                return "yellow".equals(apple.getColor());
            }
        });
System.out.println(yellowList);

2、使用lamda表达式改写

2.1、优点:相比较上面的例子

  1. 一个是代码量比较大
  2. 另一个是this的混淆(这个理由有点牵强)
    如下在这个匿名类中输出的是多少
    在这里插入图片描述
    当然是5了
  3. 最重要的是java8内存的变化
    在这里插入图片描述

在这里插入图片描述
可以看出jdk8比jdk6少了一个P,多了M、CCS
具体后面再说

2.2、使用

当一个接口中有且只有一个抽象方法我们就可以使用lamda表达式(default、static方法除外)
接口上可以标上注解@FunctionalInterface(也可以不写这个注解,它起到标识验证的作用)

 @FunctionalInterface
    public interface AppleFilter {
        boolean filter(Apple apple);
    }

在这里插入图片描述
还可以继续简写
参数类型可以推导,所以不用写参数类型
如果只有一个参数,可以去掉参数两边的括号
在这里插入图片描述

2.3、其他例子

线程的对比

       new Thread(new Runnable() {

            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        }).start();

        new Thread(() -> System.out.println(Thread.currentThread().getName())  ).start();

以及
在这里插入图片描述在这里插入图片描述
这些接口

3、lambda表达式语法

在这里插入图片描述
方法引用、类型推导、组合
他可以被定义、有传递参数、可以有返回值、可以抛出一系列异常

3.1、参数传递

在这里插入图片描述
在这里插入图片描述
红色语句两边没有加花括号,它的返回类型可以自动推导
如果加了花括号就必须写return
在这里插入图片描述

3.2、被定义(function接口)

在这里插入图片描述
lambda是一个最基本的东西,它主要是为我们 的function接口来服务的
在这里插入图片描述
在这里插入图片描述

3.3、Predicate接口

可以看出,它是给一个参数返回一个boolean值
在这里插入图片描述
在这里插入图片描述

3.4、其他合法的lambda表达式及语法总结

在这里插入图片描述
在这里插入图片描述
#### 3.5lambda语法总结

4、Lambda使用深入解析

       Runnable r1 = () -> System.out.println("Hello");

        Runnable r2 = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello");
            }
        };

        process(r1);
        process(r2);
        process(() -> System.out.println("Hello"));*/

这三个打印完全一致

4.1、Predicate<`T>

在这里插入图片描述
private static List filter(List source, Predicate predicate) {
List result = new ArrayList<>();
for (Apple a : source) {
if (predicate.test(a))
result.add(a);
}
return result;
}

        List<Apple> list = Arrays.asList(new Apple("green", 120), new Apple("red", 150));
        List<Apple> greenList = filter(list, (apple) -> apple.getColor().equals("green"));
        System.out.println(greenList);

在这里插入图片描述可以接受两个参数
在这里插入图片描述只接受一个int参数
在这里插入图片描述
在这里插入图片描述

4.2、Consumer<`T>

在这里插入图片描述

private static void simpleTestConsumer(List<Apple> source, Consumer<Apple> consumer) {
        for (Apple a : source) {
            consumer.accept(a);
        }
    }
simpleTestConsumer(list, a -> System.out.println(a));

在这里插入图片描述两个参数

 private static void simpleBiConsumer(String c, List<Apple> source, BiConsumer<Apple, String> consumer) {
        for (Apple a : source) {
            consumer.accept(a, c);
        }
    }
simpleBiConsumer("XXX", list, (a, s) -> System.out.println(s + a.getColor() + ":Weight=>" + a.getWeight()));

4.3、Function<T,R>

在这里插入图片描述

 private static String testFunction(Apple apple, Function<Apple, String> fun) {
        return fun.apply(apple);
    }
 String result3 = testFunction(new Apple("yellow", 100), (a) -> a.toString());
        System.out.println(result3);

BiFunction

private static Apple testBiFunction(String color, long weight, BiFunction<String, Long, Apple> fun) {
        return fun.apply(color, weight);
    }
        Apple a = testBiFunction("Blue", 130, (s, w) -> new Apple(s, w));
        System.out.println(a);

在这里插入图片描述
在这里插入图片描述

4.4、Supplier<`T>

在这里插入图片描述

Supplier<String> s = String::new;   //method inference.
System.out.println(s.get().getClass());

  private static Apple createApple(Supplier<Apple> supplier) {
        return supplier.get();
    }
Apple a2 = createApple(() -> new Apple("Green", 100));
System.out.println(a2);

4.5、Runnable

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
lambda表达式实际也是一个匿名函数,和内部类一样,
如果在匿名函数里使用外面的变量,则这个变量必须是final

5、Lambda方法推导详细解析-上

在这里插入图片描述
方法推导
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

5.1、可以通过类的静态方法推断

在这里插入图片描述
在这里插入图片描述

5.2、实例方法推断

在这里插入图片描述

在这里插入图片描述

5.3、已有对象的实例方法

在这里插入图片描述
在这里插入图片描述

5.4、构造函数的推导

一个参数
在这里插入图片描述
两个参数
在这里插入图片描述
三个参数(自己构造)
在这里插入图片描述
在这里插入图片描述

5.5、list.sort优化

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/uotail/article/details/88616765