常用函数接口及使用
根据以上的例子,我们定义的SkuPredicate和FileConsumer这两个接口的传参明确指定了对象(Sku和String),这样不够泛化,在JDK8中提供了一些泛化的接口,如下
接口 |
参数 |
返回类型 |
描述 |
Predicate<T> |
T |
boolean |
用于判别一个对象。比如求一个人是否为男性。 |
Consumer<T> |
T |
void |
用于接收一个对象进行处理但没有返回,比如接收一个人并打印他的名字 |
Function<T, R> |
T |
R |
转换一个对象为不同类型的对象 |
Supplier<T> |
None |
T |
提供一个对象 |
UnaryOperator<T> |
T |
T |
接收对象并返回同类型的对象 |
BinaryOperater<T> |
(T, T) |
T |
接收两个同类型的对象,并返回一个原类型对象 |
函数式接口示例:

rt.jar预制了很多类似的函数式接口

从上面看到,为基础类型提供了很多函数式接口,供我们选择,选择基础类型函数式接口的好处是不会装箱拆箱,提升了很大性能提升。在上面看到的Function函数式接口,就是一种很泛化的接口,适合处理非基础类型的接口。
方法引用
有时我们会看到如下的代码
1 2 3 4 5
| Optional.ofNullable(cartSkuList) .map(List::stream) .orElseGet(Stream::empty) .sorted(Comparator.comparing(Sku::getTotalNum)) .forEach(resultSluList::add);
|
看到代码中有很多的::
,这是什么语法呢?是方法引用。
调用特定方法的Lambda表达式的一种快捷写法,可以让你重复使用现有的方法定义,并像Lambda表达式一样传递他们。
Sku |
:: |
getSkuPrice |
目标引用 |
双冒号分隔符 |
方法名 |
指向静态方法的方法引用
1 2 3 4 5 6 7 8
|
public void test1() { Consumer<String> consumer1 = (String number) -> Integer.parseInt(number); Consumer<String> consumer2 = Integer::parseInt; }
|
指向任意类型实例方法的方法引用
1 2 3 4 5 6 7 8
|
public void test2() { Consumer<String> consumer1 = (String str) -> str.length(); Consumer<String> consumer2 = String::length; }
|
指向现有对象的实例方法的方法引用
1 2 3 4 5 6 7 8 9
|
public void test3() { StringBuilder stringBuilder = new StringBuilder(); Consumer<String> consumer1 = (String str) -> stringBuilder.append(str); Consumer<String> consumer2 = stringBuilder::append; }
|
方法引用精讲
Lambda表达式的由来
使用实体类代表判断逻辑
1 2
| List<Sku> skus = CartService.filterSkus(cartSKuList, new SkuTotalPricePredicate());
|
使用匿名类代表判断逻辑
1 2 3 4 5 6 7 8
| List<Sku> skus = CartService.filterSkus(cartSKuList, new SkuPredicate() { @Override public boolean test(Sku sku) { return sku.getSkuPrice() > 1000; } });
|
使用Lambda表达式代表判断逻辑
1 2 3
| List<Sku> skus = CartService.filterSkus(cartSKuList, (Sku sku) -> sku.getSkuPrice() > 1000);
|
方法引用的由来
使用方法引用代表判断逻辑
1 2 3 4 5 6 7 8 9
| public class Sku { public Boolean comparePrice() { return this.skuPrice > 1000; } }
List<Sku> result = CartService.filterSkus(cartSkuList, Sku::comparePrice);
|
方法引用的作用
- 方法引用是用来直接访问类或者实例的已存在的方法或者构造方法。
方法引用的表达形式
方法引用分类
方法引用类型 |
表示形式 |
指向静态方法 |
Class::staticMethod |
指向现有对象的实例方法 |
object::instanceMethod |
执行任意类型的实例方法 |
Class::instanceMethod |
指向构造方法 |
Class::new |
实战案例:四种方法引用的使用场景及区别
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| package com.java.example;
import java.util.ArrayList; import java.util.List; import java.util.Optional;
public class MethodReferenceTest {
static class Sku { private String skuName; private Integer skuPrice;
public Integer getSkuPrice() { return skuPrice; }
public static int staticComparePrice(Sku sku1, Sku sku2) { return sku1.getSkuPrice() - sku2.getSkuPrice(); }
public int instanceComparePrice(Sku sku) { return this.getSkuPrice() - sku.getSkuPrice(); } }
class PriceComparator { public int instanceComparePrice(Sku sku1, Sku sku2) { return sku1.getSkuPrice() - sku2.getSkuPrice(); } }
public void test() { List<Sku> skuList = new ArrayList<>(); skuList.sort((sku1, sku2) -> sku1.getSkuPrice() - sku2.getSkuPrice());
skuList.sort(Sku::staticComparePrice); skuList.sort((Sku sku1, Sku sku2) -> { return Sku.staticComparePrice(sku1, sku2); });
PriceComparator priceComparator = new PriceComparator(); skuList.sort(priceComparator::instanceComparePrice); skuList.sort((Sku sku1, Sku sku2) -> { return priceComparator.instanceComparePrice(sku1, sku2); });
skuList.sort(Sku::instanceComparePrice); skuList.sort((Sku object, Sku sku) -> { return object.instanceComparePrice(sku); });
Optional.ofNullable(skuList).orElseGet(ArrayList::new); } }
|