lambda表达式是函数式编程的核心,即隐式函数,没有函数名,只有函数体。
lambda表达式特点
(1)代码简单
(2) 对象不变性
lambda表达式的方法引用
(1)静态方法:ClassName::methodName
(2)实例方法:instance::methodName
(3)超类的实例方法:super::methodName
(4)类型上的类型引用:ClassName::methodName
(5)构造方法引用:Class::new
(6)数组构造方法引用:TypeName[]::new
重点:通过@FunctionalInterface类型接口,定义构造函数:
class User{
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
}
class ConstrMethodRef{
// 通过 User 的工厂类 UserFactory(函数式接口),使用User::new创建接口实例时,
// 系统会根据 UserFacroty.create() 的函数签名选择合适的 User 构造函数
@FunctionalInterface
interface UserFactory<U extends User>{
// 函数式接口定义:只有一个抽象方法;其它(静态、默认)方法不做限制
U create(int id, String name);
}
static UserFactory<User> userRef = User::new;
public static void main(String[] args) {
List<User> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(userRef.create(i, "xiao" + Integer.toString(i)));
}
list.stream().map(User::getName).forEach(System.out::print);
}
}
第二次结果还是原数组,说明函数式编程的不变性(所以函数式并行编程不用考虑线程安全性问题,因为每个对象都是不变的);
int[] nums = {1, 2, 3, 4};
String[] strs = {"xsx", "csw", "dwfwfve", "efwe", "frwqweqa"};
// 1.将所有元素 +1,并打印;
Arrays.stream(nums).map((x) -> x = x + 1).forEach(System.out::print); // {2,3,4,5}
// 2.传入的还是 nums,即使 上一条语句 执行过了,所以打印的还是原数组
Arrays.stream(nums).forEach(System.out :: print); // {1,2,3,4}
// 3.元素为奇数 则加1,打印
Arrays.stream(nums).map(x -> (x % 2 == 0 ? x : x + 1)).forEach(System.out::println);
// 4.排序时的比较器(对strs字符串数组排序,规则:先按字符串长度升序,再按大小写不敏感的字母顺序排序)
Arrays.sort(strs, Comparator.comparingInt(String::length).thenComparing(String.CASE_INSENSITIVE_ORDER));
// 5.
流式编程的演变:
// 1.通过临时实例化一个 Consumer 对象,重写其中的方法,实现流式编程
Arrays.stream(strs).forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
// 2.推断Consumer接口,省略Consumer实例
Arrays.stream(strs).forEach((final String x) -> { System.out.println(x); });
// 3.省略 参数类型、final 和 大括号;
Arrays.stream(strs).forEach((x) -> System.out.println(x));
// 4.可以使用方法引用的,直接使用方法引用
Arrays.stream(strs).forEach( System.out::println);
// 5. 使用
// 通过 Consumer 定义两个方法引用
IntConsumer outPrint = System.out::println;
IntConsumer errPrint = System.err::println;
// 直接在stream中使用定义的方法引用
Arrays.stream(nums).forEach(outPrint.andThen(errPrint));
并行流
// 1.获取指定范围内的质数总数
IntStream.range(1, 10000).parallel().filter(PrimeUtil::isPrime).count();
// 2.从集合得到并行流
double avg = list.parallelStream().mapToInt(s -> s.id).average().getAsDouble();
// 3.并行排序
Arrays.parallelSort(nums);
// 4.并行赋值
Arrays.parallelSetAll(nums, (i) -> new Random().nextInt());
lambda表达式实现
lambda表达式的实现类似于匿名类的实现,只是写法上有所区别,通过编译反编译lambda表达式,可以清楚看到。
问题:如何编译、反编译、查看lambda表达式的实现方式?