Java的Lambda表达式学习笔记:使用lambda表达式

跟着官网的教程一起深入学习Lambda表达式:

Using Lambdas Expressions in Your Application - Dev.java

二、运用Lambda表达式到程序中

JDK8加了一个新包java.util.function,里面定义了很多函数式接口,主要分为4类:Supplier<T>、

Consumer<T>、Predicate<T>、Function<T, R>

1.想获取一个新对象使用Supplier<T>

Supplier没有入参,会返回一个对象,而且每次调用都会返回一个新的对象

@FunctionalInterface
public interface Supplier<T> {

    T get();
}

下面是一个简单的Supplier实现如下:

public static void main(String[] args) {
    Supplier<String> str = () -> "hello Duke";
    System.out.println(str.get());
}

 再看一个实现示例:

public static void main(String[] args) {
    Random random = new Random(314L);
    Supplier<Integer> supplier = () -> random.nextInt(10);
    for (int i = 0; i < 5; i++) {
        System.out.println(supplier.get());
    }
}

上面的操作会两次装箱和拆箱操作,一个是random.nextInt(10)返回int时会自动装箱为Integer;另一个是调用get后获得随机数后(这里我自己也不是很懂,有人懂的赐教一下),这样的自动装箱拆箱会影响性能。考虑到这个问题,JDK提供了优化的方法供使用。比如提供了专门的IntSupplier<T>:

@FunctionalInterface
public interface IntSupplier {

    int getAsInt();
}

用IntSupplier修改上面的例子:

Random random = new Random(314L);
IntSupplier newRandom = () -> random.nextInt();


for (int i = 0; i < 5; i++) {
    int nextRandom = newRandom.getAsInt();
    System.out.println("next random = " + nextRandom);
}

JDK提供了四个这样的专用Supplier:IntSupplierBooleanSupplierLongSupplierDoubleSupplier.其中的get方法分别为getAsInt(),getAsBoolean(),getAsLong(),getAsDouble()

2.需要使用一个对象用Consumer<T>

 Consumer和Supplier相反,它需要入参,但不返回东西,而且它除了抽象方法还有一个default方法

@FunctionalInterface
public interface Consumer<T> {

    void accept(T t);

    // default methods removed
}

在Supplier的例子中使用Consumer:

public static void main(String[] args) {
    Random random = new Random(314L);
    IntSupplier supplier = () -> random.nextInt(10);
    Consumer<Integer> consumer = s -> System.out.println(s);

    for (int i = 0; i < 5; i++) {
        consumer.accept(supplier.getAsInt());
    }
}

Consumer和Supplier一样,考虑到性能优化,提供了专门的IntConsumer,LongConsumer,DoubleConsumer,因为它们都没有返回值,方法均为accept()。

JDK还提供了一个接收两个参数的BigConsumer<T, U>

@FunctionalInterface
public interface BiConsumer<T, U> {

    void accept(T t, U u);

    // default methods removed
}

使用BigConsumer重写写获取随机数的例子:

public static void main(String[] args) {
    BiConsumer<Random, Integer> consumer = (r, n) -> {
        for (int j = 0; j < n; j++) {
            System.out.println(r.nextInt(10));
        }
    };

    consumer.accept(new Random(314L), 5);
}

 BigConsumer也提供了专门的ObjIntConsumer,ObjLongConsumer,ObjDoubleConsumer

 3.当需要判断一个对象是否满足某个条件时用Predicate<T>

predicate常常会被用来做过滤

@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);

    // default and static methods removed
}

Predicate的基本类型专用接口有IntPredicate,LongPredicate,DoublePredicate,同时也有支持两个入参的接口BigPredicate<T, U>,但是BigPredicate没有基本类型的专用接口。

用Predicate对list做过滤:

public static void main(String[] args) {
    List<String> list = List.of("one", "two", "three", "four", "five");
    List<String> strings = new ArrayList<>(list);
    Predicate<String> predicate = s -> s.length()%2==0;

    strings.removeIf(predicate);
    System.out.println(strings);
}

输出如下:

注意这里的removeIf()会修改调用列表的内容,所以像List.of()和Arrays.asList()生成的list,调用removeIf()时会运行保存,因为这两种方式生成的列表都是不可变的。

4.从一个类型映射到另一个类型用Function<T, R>

@FunctionalInterface
public interface Function<T, R> {

    R apply(T t);

    // default and static methods removed
}

 例如:

Function<String, Integer> toLength = s -> s.length();
String word = ...; // any kind of word will do
int length = toLength.apply(word);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值