Jdk8特性lambda


Jdk8特性lambda
Jdk8特性lambda
在java的历史中,java8的变化举重若轻

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

1.1、找绿色的苹果

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

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

1.2、找红色的苹果

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

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

Jdk8特性lambda

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的混淆(这个理由有点牵强)
    如下在这个匿名类中输出的是多少
    Jdk8特性lambda
    当然是5了
  3. 最重要的是java8内存的变化
    Jdk8特性lambda

Jdk8特性lambda
可以看出jdk8比jdk6少了一个P,多了M、CCS
具体后面再说

2.2、使用

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

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

Jdk8特性lambda
还可以继续简写
参数类型可以推导,所以不用写参数类型
如果只有一个参数,可以去掉参数两边的括号
Jdk8特性lambda

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();

以及
Jdk8特性lambdaJdk8特性lambda
这些接口

3、lambda表达式语法

Jdk8特性lambda
方法引用、类型推导、组合
他可以被定义、有传递参数、可以有返回值、可以抛出一系列异常

3.1、参数传递

Jdk8特性lambda
Jdk8特性lambda
红色语句两边没有加花括号,它的返回类型可以自动推导
如果加了花括号就必须写return
Jdk8特性lambda

3.2、被定义(function接口)

Jdk8特性lambda
lambda是一个最基本的东西,它主要是为我们 的function接口来服务的
Jdk8特性lambda
Jdk8特性lambda

3.3、Predicate接口

可以看出,它是给一个参数返回一个boolean值
Jdk8特性lambda
Jdk8特性lambda

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

Jdk8特性lambda
Jdk8特性lambda
Jdk8特性lambda

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>

Jdk8特性lambda
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);

Jdk8特性lambda可以接受两个参数
Jdk8特性lambda只接受一个int参数
Jdk8特性lambda
Jdk8特性lambda

4.2、Consumer<`T>

Jdk8特性lambda

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

Jdk8特性lambda两个参数

 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>

Jdk8特性lambda

 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);

Jdk8特性lambda

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);

Jdk8特性lambda
Jdk8特性lambda

4.4、Supplier<`T>

Jdk8特性lambda

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

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

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

Jdk8特性lambda
方法推导
Jdk8特性lambda

Jdk8特性lambda
Jdk8特性lambda

Jdk8特性lambda

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

Jdk8特性lambda
Jdk8特性lambda

5.2、实例方法推断

Jdk8特性lambda

Jdk8特性lambda

5.3、已有对象的实例方法

Jdk8特性lambda
Jdk8特性lambda

5.4、构造函数的推导

一个参数
Jdk8特性lambda
两个参数
Jdk8特性lambda
三个参数(自己构造)
Jdk8特性lambda
Jdk8特性lambda

5.5、list.sort优化

Jdk8特性lambda
Jdk8特性lambda
Jdk8特性lambda
Jdk8特性lambda
Jdk8特性lambda