Java8特性:lambda表达式

作为一个稀有的Java妹子,所写的所有博客都只是当作自己的笔记,留下证据自己之前是有用心学习的~哈哈哈哈(如果有不对的地方,也请大家指出,不要悄悄咪咪的不告诉我)

一、概述

以前我们在实现接口时,一般是写一个实现类,然后重写需要调用的方法,如果不想创建实现类,就使用匿名内部类来重写方法。

public interface MyInterface {
    void test();
}

实现类重写方法

public class MyInterfaceImpl implements MyInterface {
    @Override
    public void test() {
        System.out.println("重写了该方法!!");
    }
}

匿名内部类重写方法

 MyInterface myInterface = new MyInterface() {
            @Override
            public void test() {
                System.out.println("匿名内部类重写方法!!!");
            }
        };

在有了lambda表达式后,可以简化接口的实现,达到不创建新的实现类和使用匿名内部类,使用简单的代码就可以实现接口。

 MyInterface myInterface1 = () -> System.out.println("lambda重写方法");

二、lambda表达式的格式

(params…) -> {operation}
表达式分为三个部分:
1.左边是参数,即接口方法的入参,如果是无参的,就只需要(),参数的类型可以省略不写
2.中间的是lambda的符号,-> 意为(gose to)
3.右边是方法实现的方法体,就相当于我们实现接口时,在方法体中写的代码,如果只有一句,则可以不要{},有返回值的也不需要return;如果有多句代码,则需要大括号,有返回值的接口,需要加上return;

三、Java内置的函数式接口

1、函数式接口:在jdk8以前,接口只能有抽象方法,不能有带有方法体的方法,但是在jdk8之后,接口也可以有非抽象方法,只需要在方法定义时,加上default,如果接口只能有一个抽象方法,在接口加上@FunctionalInterface注解,只有一个抽象方法的接口叫做函数式接口
2、内置的函数式接口,关注每个接口的方法,主要区别就是方法的参数和返回值,这样我们就可以不用自己去定义接口,只需要使用lambda表达式去实现它。

(1)、

@FunctionalInterface
public interface Comparator<T> {
      int compare(T o1, T o2);
}

以前需要排序集合的做法

List<User> list = new ArrayList<>();
User user1 = new User("里斯",16);
User user2 = new User("嗷嗷",56);
User user3 = new User("哈哈",23);
User user4 = new User("奥奥",16);
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
list.sort(new Comparator<User>() {
      @Override
      public int compare(User o1, User o2) {
          if(o1.getAge()>o2.getAge()){
                return 1;
          }else if(o1.getAge().equals(o2.getAge())){
               return 0;
           }else {
                return -1;
           }
   }

使用lambda表达式

 list.sort((u1,u2) -> Integer.compare(u1.getAge(),u2.getAge()));

这里我们看到方法的实现是调用了另一个方法,前提是这个方法和需要实现的方法参数和返回值一样,

public static int compare(int x, int y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }

(2)、

@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);
    
 }

这个接口有一个参数,返回值为boolean,来看一下这个接口在Collection接口中的用法

//这个方法是移除集合中满足条件的元素,注意这个方法是在接口中,所以加了default后就可以有方法体了。
default boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        boolean removed = false;
        final Iterator<E> each = iterator();
        while (each.hasNext()) {
            if (filter.test(each.next())) {
                each.remove();
                removed = true;
            }
        }
        return removed;
    }

以前的调用形式

List<User> list = new ArrayList<>();
User user1 = new User("里斯",16);
User user2 = new User("嗷嗷",56);
User user3 = new User("哈哈",23);
User user4 = new User("奥奥",16);
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
//使用匿名内部类来实现方法
list.removeIf(new Predicate<User>() {
    @Override
    public boolean test(User user) {
        if(user.getAge()>20){
              return true;
         }
        return false;
     }
});

使用lambda表达式:

List<User> list = new ArrayList<>();
User user1 = new User("里斯",16);
User user2 = new User("嗷嗷",56);
User user3 = new User("哈哈",23);
User user4 = new User("奥奥",16);
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
//表达式左边是参数u,类型可以省略,不省略的话就是User u,右边是方法体,
//返回的是boolean值,可以看到参数和返回值与Predicate接口的test
//方法是一致的。
list.removeIf(u -> u.getAge()>20);

(3)、

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
}

集合的foreach方法参数是这个接口,循环集合的元素,然后调用了该接口的accept方法。

 default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

使用lambda表达式循环输出集合元素

list.forEach(System.out::println);

println方法入参和返回值与accept一样,可以使用该方法的方法体直接实现accept方法

public void println(Object x) {
        String s = String.valueOf(x);
        synchronized (this) {
            print(s);
            newLine();
        }
    }

注意:
::双冒号可以调用接口的方法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值