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 greenApple = findGreenApple(list);
assert greenApple.size() == 2 : "不符合预期"; //断言
for (Apple apple : greenApple) {
System.out.println(apple);
}
**/
/**
//传入一个条件
List greenApples = findApple(list,"green");
System.out.println(greenApples);
**/
/**
//传入一个过滤器
List result = findApple(list,new GreenAnd150Filter());
System.out.println(result);
**/
/**
//采用匿名内部类的方式
List 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表达式?
基于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体,可泛化为以下格式
where、how(如何使用,以及在哪里使用)
什么样的接口是FunctionalInterface?
常见的可使用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之外,还有细化的Predicate,如
// BiPredicate( 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 (void accept(T t);)
//BiConsumer(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{ 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 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 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);
}
源码放在这儿