Lambda表达式:
为 @FunctionalInterface 的接口服务。该接口内只有一个抽象方法。除了default 和静态方法除外。例如:
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
语法:
例子:
下面两张方法作用相同
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("hello world");
}
};
Runnable r2 = () -> System.out.println("hello world");
r1.run();
r2.run();
用lambda 把@functionalInterface 的方法 更简便的 定义出来。
java 8 几种常用的 使用lambda 的接口:
这些接口来自 java.util.function 包
Predicate 定义:
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
* 根据给定的参数 做出判断。
**/
boolean test(T t);
}
例子:
class Apple{ //一个苹果类
private String color;
private int weight;
}
根据给定条件 选择对应的苹果
static List<Apple> filterApple(List<Apple> apples, Predicate<Apple> predicate){
List<Apple> result = new ArrayList<>();
for (Apple a :apples){
if(predicate.test(a)){
result.add(a);
}
}
return result;
}
测试:
List<Apple> list = Arrays.asList(new Apple("green",100),new Apple("red",150));
List<Apple> result = filterApple(list,apple -> apple.getColor().equals("green"));
结果:
还有 IntPredicate ,DoublePredicate, LongPredicate 分别对应 test()中的参数是 int 类型,Double, Long类型。
举例:
static List<Apple> filterAppleByweight(List<Apple> apples, LongPredicate weight){
List<Apple> result = new ArrayList<>();
for (Apple a :apples){
if(weight.test(a.getWeight())){
result.add(a);
}
}
return result;
}
调用:
filterAppleByweight(list,w -> w > 100)
还有BiPredicate , 它的test() 有两个参数。
例如:
Consumer 定义:
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*执行 基于 给定参数的 操作
*/
void accept(T t); }
举例:
static void testConsumer(List<Apple> apples, Consumer<Apple> consumer){
for (Apple a : apples){
consumer.accept(a);// 具体怎么做就要看 我们 在lambda表达式中给他传的行为。
}
}
调用:
testConsumer(list,a -> System.out.println(a));
它 也有对应两参数的 BiConsumer, Intcomsumer
Function 定义: 该接口非常常用。
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);}
举例 :给数字加上后缀
Function<Integer,String> function = a -> a+"hello";
System.out.println(function.apply(20));
BiFunction : 有三个参数,前两个是条件,最后一个是结果
举例:根据color和 weight 属性新建一个对象。
static Apple testBiFunction(String color, int weight, BiFunction<String,Integer,Apple> biFunction){
return biFunction.apply(color,weight);
}
调用:
Apple a = testBiFunction("blue",100,(c,w) -> new Apple(c,w));
System.out.println(a);
Supplier 定义:
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
举例:
static Apple createApple(Supplier<Apple> supplier){
return supplier.get();
}
Apple apple = createApple(() -> new Apple("red", 100));
System.out.println(apple);
Supplier<String> su = String::new;
System.out.println(su.get().getClass());
Lambda 表达式方法推导:
case1:
如果一个类中有静态方法,可以使用方法推导
例如:
int num = Integer.parseInt("123");
//使用方法推导
Function<String,Integer> fun1 = Integer::parseInt;
Integer res = fun1.apply("123");
System.out.println(res);
因为Integer.parseInt 方法 有两个参数,且返回一个参数类型,用Function 即可。
case2:
对类中的非静态方法进行推导
BiFunction<String,Integer,Character> f2 = String::charAt;
Character c = f2.apply("abc",2);
System.out.println(c);
对非静态方法推导时,需要先把类的名称传进去,在把方法的参数和返回值参数类型 传进去。
case3:
对实例化 对象的方法进行推导
String s = new String("hello");
Function<Integer, Character> f3 = s::charAt;
Character c2 = f3.apply(2);
System.out.println(c2);
因为已经实例化了对象,所以方法推导时不需要在传入类的名称了。