java中lambda表达式的实现

一.示例代码

package lambda.examples._02;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class App {

	List<Apple> getAppleList() {
		List<Apple> list = new ArrayList<Apple>();
		list.add(new Apple("green", 100));
		list.add(new Apple("red", 150));
		list.add(new Apple("green", 50));
		return list;
	}

	public void test() {
		List<Apple> list = getAppleList();
		list.sort(Comparator.comparing(Apple::getWeight));
		list.forEach(System.out::println);
	}

	public static void main(String[] args) {
		new App().test();
	}

}

class Apple {
	private String color;
	private int weight;

	public Apple(String color, int weight) {
		super();
		this.color = color;
		this.weight = weight;
	}

	@Override
	public String toString() {
		return "Apple [color=" + color + ", weight=" + weight + "]";
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}

	public int getWeight() {
		return weight;
	}

	public void setWeight(int weight) {
		this.weight = weight;
	}
}

二.代码分析

输出如下:

Apple [color=green, weight=50]
Apple [color=green, weight=100]
Apple [color=red, weight=150]

在test方法中我们使用了java8中的新特性lambda表达式,
list.sort()需要传入一个Comparator接口的实现类,在java8之前我们通常使用匿名内部类实现,类似这样

		list.sort(new Comparator<Apple>() {
			@Override
			public int compare(Apple a, Apple b) {
				return a.getWeight() > b.getWeight() ? 1 : (a.getWeight() < b.getWeight() ? -1 : 0);
			}
		});

可以看出来其实有用的就一行代码,还要写那么多,所以对于这种只有一个抽象方法的接口我们称之为函数式接口,我们直接用lambda表达式实现,代码如下:

list.sort((a, b) -> a.getWeight() > b.getWeight() ? 1 : (a.getWeight() < b.getWeight() ? -1 : 0));

分析下什么意思,sort可以接受Comparator类型的接口实现类,Comparator是一个函数式接口,他的抽象方法是

			@Override
			public int compare(Apple a, Apple b) {
				return a.getWeight() > b.getWeight() ? 1 : (a.getWeight() < b.getWeight() ? -1 : 0);
			}

我们简写为

	(a, b) -> a.getWeight() > b.getWeight() ? 1 : (a.getWeight() < b.getWeight() ? -1 : 0)

即可
->意为goto,前面的是方法的参数,后面是结果,如果只有一行就不写return,否则需要用{}括起来,并且return返回值,例如:

		list.sort((a, b) -> {
			if (a.getWeight() > b.getWeight())
				return 1;
			if (a.getWeight() < b.getWeight())
				return -1;
			return 0;
		});

这里ab我们并不需要写类型,编译器会根据list的类型做推断

三.lambda如何实现

代码如下:

package lambda.examples._02;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class App {

	List<Apple> getAppleList() {
		List<Apple> list = new ArrayList<Apple>();
		list.add(new Apple("green", 100));
		list.add(new Apple("red", 150));
		list.add(new Apple("green", 50));
		return list;
	}

	public void test() {
		List<Apple> list = getAppleList();
		list.sort(new Comparator<Apple>() {
			@Override
			public int compare(Apple a, Apple b) {
				return a.getWeight() > b.getWeight() ? 1 : (a.getWeight() < b.getWeight() ? -1 : 0);
			}
		});
		list.sort((a, b) -> a.getWeight() > b.getWeight() ? 1 : (a.getWeight() < b.getWeight() ? -1 : 0));
		list.forEach(System.out::println);
	}

}

class Apple {
	private String color;
	private int weight;

	public Apple(String color, int weight) {
		super();
		this.color = color;
		this.weight = weight;
	}

	@Override
	public String toString() {
		return "Apple [color=" + color + ", weight=" + weight + "]";
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}

	public int getWeight() {
		return weight;
	}

	public void setWeight(int weight) {
		this.weight = weight;
	}
}
package lambda.examples._02;

import java.io.IOException;

public class OtherApp {
	public static void main(String[] args) throws IOException {
		new App();
		System.in.read();
	}
}

现在用OtherApp的main方法初始化一个App类型的对象(这是为了加载App类),然后阻塞住查看字节码

java -classpath "%JAVA_HOME%/lib/sa-jdi.jar" sun.jvm.hotspot.HSDB

jps查看pid
在这里插入图片描述
使用hsdb attch 4744
打开Tools -> Class Brower
搜索App
在这里插入图片描述
查看class,发现其中有一个方法叫

private static [synthetic] int lambda$0(lambda.examples._02.Apple, lambda.examples._02.Apple)@0x000000001da80b80;

synthetic表示这是编译器生成的方法

所以说lambda语句会在所在的类被加载时,被jvm解析为该类中的一个private static 方法,接收lambda语句中的参数并且返回 lambda语句 -> 后面的结果(如果有返回值)

Create .class File

执行

javap -c -p App.class

结果如下:

Compiled from "App.java"
public class lambda.examples._02.App {
  public lambda.examples._02.App();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

			.
			.
			.
			略
			.
			.
			.

  private static int lambda$0(lambda.examples._02.Apple, lambda.examples._02.Apple);
    Code:
       0: aload_0
       1: invokevirtual #72                 // Method lambda/examples/_02/Apple.getWeight:()I
       4: aload_1
       5: invokevirtual #72                 // Method lambda/examples/_02/Apple.getWeight:()I
       8: if_icmple     15
      11: iconst_1
      12: goto          31
      15: aload_0
      16: invokevirtual #72                 // Method lambda/examples/_02/Apple.getWeight:()I
      19: aload_1
      20: invokevirtual #72                 // Method lambda/examples/_02/Apple.getWeight:()I
      23: if_icmpge     30
      26: iconst_m1
      27: goto          31
      30: iconst_0
      31: ireturn
}

可以清晰的看到我们在lambda语句里定义的逻辑

所以

lambda语句会在类被jvm加载时解析为该类的private static 方法随之初始化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值