Java8新特性(一)Lambda表达式
-
lambda出现的原因
-
减少代码量
-
避免匿名内部类参数之间的混淆
-
降低内存消耗,使用lambda表达式比使用匿名内部类或者子类的方式更加节省空间,主要原因还是因为java8后jvm结构发生了变化
-
举个栗子:过滤指定特征的苹果
//苹果实体类
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Apple {
private String color;
private long weight;
}
//过滤苹果类
public class FilterApple {
//需求一:删选出指定颜色的苹果
public static List<Apple> findGreenApple(List<Apple> apples){
List<Apple> list = new ArrayList<>();
for (Apple apple : apples) {
if("green".equals(apple.getColor())){
list.add(apple);
}
}
return list;
}
//需求二:筛选出颜色为红色的苹果,更改策略,采用条件进行过滤
public static List findApple(List<Apple> apples,String color){
List<Apple> list = new ArrayList<>();
for (Apple apple : apples) {
if(color.equals(apple.getColor())){
list.add(apple);
}
}
return list;
}
//需求三:根据苹果的各种条件筛选,如颜色和重量,利用策略模式
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 GreenAnd150Filter implements AppleFilter {
@Override
public boolean filter(Apple apple) {
return "green".equals(apple.getColor())&&apple.getWeight()>=160;
}
}
public static void main(String[] args) throws InterruptedException {
List<Apple> list = Arrays.asList(
Apple.builder().color("green").weight(150).build(),
Apple.builder().color("yellow").weight(120).build(),
Apple.builder().color("green").weight(180).build());
/**
//寻找绿色的苹果
List<Apple> greenApple = findGreenApple(list);
assert greenApple.size() == 2 : "不符合预期"; //断言
for (Apple apple : greenApple) {
System.out.println(apple);
}
**/
/**
//传入一个条件
List<Apple> greenApples = findApple(list,"green");
System.out.println(greenApples);
**/
/**
//传入一个过滤器
List<Apple> result = findApple(list,new GreenAnd150Filter());
System.out.println(result);
**/
/**
//采用匿名内部类的方式
List<Apple> yellowList = findApple(list, new AppleFilter() {
@Override
public boolean filter(Apple apple) {
return "yellow".equals(apple.getColor());
}
});
System.out.println(yellowList);
**/
}
}
//为什么匿名内部类参数容易混淆...
public class AnonymousInnerClass {
public final int value = 4;
public void doIt(){
int value = 6;
Runnable r = new Runnable() {
public final int value = 7;
@Override
public void run() {
int value = 8;
System.out.println(this.value);
}
};
r.run();
}
public static void main(String[] args) {
AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass();
anonymousInnerClass.doIt();
}
}
-
lambda表达式的简单使用
-
什么情况使用lambda表达式?
- 接口且接口中只含有一个方法
- default或静态方法除外
-
基于lambda表达式对以上栗子进行改进
-
java8中,如果一个接口只有一个方法,可视为一个FunctionInterface,表示它可以使用lambda进行操作。
List<Apple> lambdaResult = findApple(list, (Apple apple) -> { return apple.getColor().equals("green"); }); //上式可以简写,因为只有一个参数,它会推导它是apple类型的,只有一个参数,也可以把括号去掉 List<Apple> lambdaResult2 = findApple(list, (apple) -> { return apple.getColor().equals("green"); }); //扩展--lambda表达式需要满足的条件: //有且只有一个方法,default和static方法除外,它会在编译的时候判断,可以不标注它为FunctionalInterface,类似的有Runner
-
-
lambda表达式语法
-
语法:以(o1,o2) -> o1.getColor().compareTo(o2.getColor());为例,其中拆解为三部分:参数列表,箭头,lambda体,可泛化为以下格式
- ((parameters) -> expression
- (parameters) -> {statments;}
- ()->{}
-
where、how(如何使用,以及在哪里使用)
-
什么样的接口是FunctionalInterface?
- 只有一个抽象的方法,default和static方法除外(1.8新特性)
-
常见的可使用lambda的方法
//传入一个参数,判断其是否满足条件或其他 Predicate boolean test(T t); //消费,处理 Consumer void accept(T t); //传入一个T类型参数,返回一个R类型的,两者可以相同 Function<T,R> R apply(T t); //提供一个参数,只是get一个东西 Supplier<T> T get();
-
-
几个简单的lambda栗子
public class LambdaExpression { public interface Test{ public String fun(); } public static void main(String[] args) { //1.定义比较器,传入比较器进行比较 Comparator<Apple> byColor = new Comparator<Apple>() { @Override public int compare(Apple o1, Apple o2) { return o1.getColor().compareTo(o2.getColor()); } }; List<Apple> list = Collections.emptyList(); list.sort(byColor); //引入lambda表达式优化 //类型推导,可以不用写return Comparator<Apple> byColor2 = (o1,o2)->o1.getColor().compareTo(o2.getColor()); list.sort(byColor2); //可以写return, =(o1,o2) -> {return o1.getColor().compareTo(o2.getColor());}; //2.lambda表达式举例:(String s) -> s.length();返回类型:Function Function<String, Integer> flambda = s -> s.length(); System.out.println(flambda.apply("hello")); //5 //3.Predicate使用示例:(Apple a) -> a.getColor().equals("green");返回类型:Predicate Predicate<Apple> appleFilter = a -> a.getColor().equals("green"); } }
-
lambda表达式的详细使用
-
通过栗子了解lambda表达式的使用
public class LambdaUsage { @FunctionalInterface public interface Adder{ int add(int a,int b); }; //@FunctionalInterface,不是,处理有父类的add抽象方法外,还有自己的重载的add方法实现 public interface SmartAdder extends Adder{ int add(long a,long b); }; @FunctionalInterface public interface Empty extends Adder{ } @FunctionalInterface public interface DefaultAddr extends Adder{ default int otherAddr(int a,int b){ return a+b; } } public static void main(String[] args) { //1.lambda表达式替代匿名内部类 WhereToUsage(); //通过栗子了解Predicate的用法:过滤指定颜色和重量的苹果 List<Apple> greenList = filter(list, apple -> apple.getColor().equals("green")); System.out.println(greenList); //2.除Predicate<T>之外,还有细化的Predicate,如 // BiPredicate<T,U>( boolean test(T t, U u);), IntPredicate(boolean test(int value);), // LongPredicate(boolean test(long value);), DoublePredicate(boolean test(double value);) List<Apple> weightList = filterByWeight(list,value -> value>100); System.out.println(weightList); //return返回值,表达式需要使用{}隔离 List<Apple> result = filterByBiPredicate(list,(color,weight)->{return color.equals("green")&&weight>100;}); List<Apple> result2 = filterByBiPredicate(list,(color,weight)->(color.equals("green")&&weight>100)); System.out.println(result); System.out.println(result2); //3.Consumer的用法 //Consumer<T> (void accept(T t);) //BiConsumer<T,U>(void accept(T,U);) simpleTestConsumer(list,a-> System.out.println(a)); simpleBiConsumer(list,(a,b)-> System.out.println("颜色为:"+a+"重量为:"+b)); simpleBiConsumer2(list,(a,b)-> System.out.println("信息为:"+a.getWeight()+"颜色为:"+a.getColor())); //4.Function的用法,传入一个苹果,传出的苹果String,两种类型可相同可不同 Apple apple = Apple.builder().weight(120).color("red").build(); String result3 = testFunction(apple, a -> a.toString()); System.out.println(result3); String color = "红色"; long weight = 105L; testBiFunction(color,weight,(c,w)->new Apple(c,w)); compute(3,r -> r*r); compute(3,r -> r+r); //Function中,compose是其默认方法,接受一个function作为参数,将参数function的执行结果 //作为参数给调用的function,以此实现两个function组合的功能 int b = compute(2,r -> r*r,w -> w+w); //(2+2)*(2+2) = 16 //Function andThen,接收一个function作为参数,与compse不同的是,先执行本身的apply方法, // 将执行的结果作为参数给参数中的function。 andThen(4,r -> r+1, w -> w*2); //(4+1)*2 = 10 IntFunction<Double> f = i -> i * 100d; Double result4 = f.apply(10); Supplier<String> s = String::new; System.out.println(s.getClass()); //5.()->expression用法 createApple(() -> new Apple("green",120)); int i = 0; Runnable r = new Runnable() { @Override public void run() { //i++; System.out.println(i); } }; Runnable r2 = () -> System.out.println(i); } private static Apple createApple(Supplier<Apple> supplier){ return supplier.get(); } public static int andThen(int a,Function<Integer,Integer> function,Function<Integer,Integer> function2){ return function.andThen(function2).apply(a); } private static int compute(int a,Function<Integer,Integer> function,Function<Integer,Integer> function2){ return function.compose(function2).apply(a); } private static int compute(int a,Function<Integer,Integer> function){ return function.apply(a); } //两个输入,一个输出 private static Apple testBiFunction(String color,Long weight,BiFunction<String,Long,Apple> function){ return function.apply(color,weight); } //一个传入->一个传出 private static String testFunction(Apple apple,Function<Apple,String> function){ return function.apply(apple); } private static void WhereToUsage(){ Runnable r = () -> System.out.println(Thread.currentThread().getName()); Runnable r2 = new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()); } }; process(r); process(r2); process(()->{ System.out.println(Thread.currentThread().getName()); }); } private static void process(Runnable r){ r.run(); } private static List<Apple> filter(List<Apple> source, Predicate<Apple> predicate){ List<Apple> result = new ArrayList<>(); for (Apple apple : source) { if(predicate.test(apple)){ result.add(apple); } } return result; } private static List<Apple> filterByWeight(List<Apple> source, LongPredicate predicate){ List<Apple> result = new ArrayList<>(); for (Apple apple : source) { if(predicate.test(apple.getWeight())){ result.add(apple); } } return result; } private static List<Apple> filterByBiPredicate(List<Apple> source, BiPredicate<String,Long> predicate){ List<Apple> result = new ArrayList<>(); for (Apple apple : source) { if(predicate.test(apple.getColor(),apple.getWeight())){ result.add(apple); } } return result; } private static void simpleTestConsumer(List<Apple> source,Consumer<Apple> consumer){ for (Apple apple : source) { consumer.accept(apple); } } private static void simpleBiConsumer(List<Apple> source,BiConsumer<String,Long> consumer){ for (Apple apple : source) { consumer.accept(apple.getColor(),apple.getWeight()); } } private static void simpleTestConsumer(List<Apple> source,Consumer<Apple> consumer){ for (Apple apple : source) { consumer.accept(apple); } } private static void simpleBiConsumer(List<Apple> source,BiConsumer<String,Long> consumer){ for (Apple apple : source) { consumer.accept(apple.getColor(),apple.getWeight()); } } private static void simpleBiConsumer2(List<Apple> source,BiConsumer<Apple,String> consumer){ for (Apple apple : source) { consumer.accept(apple,apple.getColor()); } } }
-
lambda表达式之类型推导、方法引用、方法推导、组合lambda表达式
public class MethodReference { public static void main(String[] args) { //以下三种效果相同 Consumer<String> consumer = (s) -> System.out.println(s); useConsumber(consumer,"Hello World !"); useConsumber(s -> System.out.println(s),"Hello World"); useConsumber(System.out::println,"Hello World"); //排序,通过color的ascii码 List<Apple> list = Arrays.asList(new Apple("Green",110), new Apple("Red",123), new Apple("Yellow",180)); System.out.println(list); //sort方法底层:@FunctionalInterface public interface Comparator<T>{ boolean equals(Object obj);} list.sort((a1,a2) ->{ return a1.getColor().compareTo(a2.getColor());}); list.sort((a1,a2)->a1.getColor().compareTo(a2.getColor())); list.stream().forEach(a->System.out.println(a)); list.stream().forEach(System.out::println); //什么时候需要函数推导 list.stream().forEach(a -> System.out.println(a)); //循环遍历,将list中数据比遍历出来 list.stream().forEach(System.out::println); //循环遍历,将list中数据比遍历出来 //双冒号运算操作符是类方法的句柄,是lambda表达式的一种简写 /** * x -> System.out.println(x) 简化为 System.out::println 的过程称之为 eta-conversion * System.out::println 简化为 x -> System.out.println(x) 的过程称之为 eta-expansion * 举例: * person -> person.getAge();可以替换为Person::getAge * x -> System.out.println(x)可以替换成System.out::println * */ /*BiFunction<String, Integer, Character> f2 = String::charAt; Character c = f2.apply("hello",3); System.out.println(c);*/ //1.通过静态方法去创建: int value = Integer.parseInt("123"); Function<String,Integer> f = Integer::parseInt; Integer apply = f.apply("123"); System.out.println(apply); //2.可以通过对象的一个实例方法去推断,如一个类方法 //需要一个类的成员方法,需要传入这个类本身 BiFunction<String,Integer,Character> f2 = String::charAt; Character c= f2.apply("hello",3); System.out.println(c); test t = new MethodReference().new test(); BiFunction<test, Integer, Integer> getNumber = test::getNumber; int result = getNumber.apply(t,5); System.out.println(result); //3.可以使用对象存在一个实例方法去做取代 String string = new String("hello"); Function<Integer ,Character> f3 =string::charAt; Character c1 = f3.apply(2); testFunction(string,a->a.length()); System.out.println(c1); //方法推导部分 //supplier<T>: T get(); one parameter Supplier<String> supplier = String::new; String s = supplier.get(); System.out.println(s); //two parameters BiFunction<String,Long,Apple> appleBiFunction = Apple::new; Apple apple = appleBiFunction.apply("Red", 120l); System.out.println(apple); //three parameters ThreeFunction<String,String,Long,ComplexApple> appleThreeFunction = ComplexApple::new; ComplexApple complexApple = appleThreeFunction.apply("Red", "苹果", 120L); System.out.println(complexApple); List<Apple> list2 = Arrays.asList(new Apple("Green",110), new Apple("Red",123), new Apple("Yellow",180)); list2.sort(Comparator.comparing(Apple::getColor)); } private class test{ public int getNumber(int n){ return n+1; } } private static void testFunction(String str,Function<String,Integer> function){ function.apply(str); } private static <T> void useConsumber(Consumer<T> consumer,T t){ consumer.accept(t); consumer.accept(t); } } @FunctionalInterface public interface ThreeFunction<T,U,K,R>{ R apply(T t,U u,K k); }