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、优点:相比较上面的例子
- 一个是代码量比较大
- 另一个是this的混淆(这个理由有点牵强)
如下在这个匿名类中输出的是多少
当然是5了 - 最重要的是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表达式及语法总结
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);
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、构造函数的推导
一个参数
两个参数
三个参数(自己构造)