Java8实战之Lambda表达式

本文深入探讨Java中的Lambda表达式,展示其如何简化代码并提高灵活性。通过具体案例,如筛选用户列表,对比不同实现方式,包括匿名内部类、策略模式、Lambda表达式和Stream API,突出Lambda的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

Lambda 是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

示例

我们先来回顾一下匿名内部类的写法:

// 原始匿名内部类
@Test
public void test1() {

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            System.out.println("hello world");
        }
    };
    runnable.run();
}

上面所示的是原始的匿名内部类的写法,主体内容需要写好多行代码。

下面我们来看一下使用lambda表达式的写法:

// 从匿名内部类到Lambda 表达式
@Test
public void test2() {
    Runnable runnable = () -> System.out.println("hello world");
    runnable.run();
}

原始匿名内部类的方式需要写好多行代码,lambda表达式一行就搞定了。

感受到了lambda的魅力了吧,别急,精彩的还在后面呢!

假设我们现在有一个需求,就是根据条件来筛选用户,比如筛选性别为男的用户。

定义一个用户类:

public class User {
    private String name; // 名称
    private String gender; // 性别
    private int age; // 年龄

    public User(String name, String gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", age=" + age +
                '}';
    }
}

定义一个根据性别筛选性别为男的方法:

/**
  * 筛选出性别为男的用户
  *
  * @param users
  * @return
  */
 public List<User> filterUserByGender(List<User> users) {
     List<User> result = new ArrayList<>();
     for (User user : users) {
         if ("男".equals(user.getGender())) {
             result.add(user);
         }
     }
     return result;
 }

定一个成员变量,用户list:

List<User> userList = new ArrayList<>(Arrays.asList(
            new User("小明", "男", 20),
            new User("小红", "女", 30),
            new User("小张", "男", 40)
    ));

测试:

// 需求:筛选用户
@Test
public void test3() {
    List<User> users = filterUserByGender(userList);
    for (User user : users) {
        System.out.println(user);
}

输出结果:

User{name='小明', gender='男', age=20}
User{name='小张', gender='男', age=40}

OK,筛选性别为男的用户的功能实现了,那假设现在又要筛选年龄大于30岁的用户呢?
有同学会想到,将筛选性别为男的方法copy一份,判断条件改一下不就行了。我们来实现一下:

/**
 * 筛选年龄大于30的用户
 *
 * @param users
 * @return
 */
public List<User> filterUserByAge(List<User> users) {
    List<User> result = new ArrayList<>();
    for (User user : users) {
        if (user.getAge() > 30) {
            result.add(user);
        }
    }
    return result;
}

测试:

 // 需求:筛选用户
 @Test
 public void test3() {
     List<User> users = filterUserByGender(userList);
     for (User user : users) {
         System.out.println(user);
     }

     System.out.println("-------------------------------------");

     List<User> users1 = filterUserByAge(userList);
     for (User user : users1) {
         System.out.println(user);
     }
 }

输出结果:

User{name='小明', gender='男', age=20}
User{name='小张', gender='男', age=40}
-------------------------------------
User{name='小张', gender='男', age=40}

OK,筛选年龄大于30岁的功能也实现,但是仔细想想,上面的实现方式虽然能实现功能,但代码太冗余了,复用率太低了。
下面我们来优化一下。

优化方式一:使用策略模式:

定义一个范型Filter接口:

public interface Filter<T> {
    boolean test(T t);
}

定义相关的过滤器:

筛选年龄大于三十的用户:

public class UserFilterByAge implements Filter<User> {
    @Override
    public boolean test(User user) {

        if(user.getAge() > 30){
            return true;
        }
        return false;
    }
}

筛选性别为男的用户:

public class UserFilterByGener implements Filter<User> {

    @Override
    public boolean test(User user) {
        if("男".equals(user.getGender())){
            return true;
        }
        return false;
    }
}

定义一个筛选方法:

public List<User> filterUser(List<User> users, Filter<User> filter) {
  List<User> result = new ArrayList<>();
    for (User user : users) {
        if (filter.test(user)) {
            result.add(user);
        }
    }
    return result;
}

测试:

 // 优化方式一:使用策略设计模式
@Test
public void test4() {
    List<User> users = filterUser(userList, new UserFilterByGener());
    for (User user : users) {
        System.out.println(user);
    }

    System.out.println("-------------------------------------");

    List<User> users1 = filterUser(userList, new UserFilterByAge());
    for (User user : users1) {
        System.out.println(user);
    }
}

输出结果:

User{name='小明', gender='男', age=20}
User{name='小张', gender='男', age=40}
-------------------------------------
User{name='小张', gender='男', age=40}

可以看到,我们只需要传入不同的筛选策略即可,即使后面需要增加其它筛选条件,也只需新增实现类即可。

有的同学看到这里可能想说,每加一个筛选条件,就需要增加相应的策略类,策略类里面起到的作用的其实就一个条件判断,显得有些多余。

我们带着这个问题,接着优化。
优化方式二:匿名内部类:

// 优化方式二:匿名内部类
@Test
 public void test5() {
     List<User> users = filterUser(userList, new Filter<User>() {
         @Override
         public boolean test(User user) {
             return user.getAge() > 30;
         }
     });

     for (User user : users) {
         System.out.println(user);
     }
 }

我们结合匿名内部类,重写了test方法,实现自己想要的筛选条件,这样就不用新增策略类了。

既然可以使用匿名内部类,在文章开头,我们有讲到匿名内部类结合lambda的使用方式,我们来改成lambda的方式。
优化方式三:lambda表达式:

// 优化方式三:lambda表达式
@Test
public void test6() {
    List<User> users = filterUser(userList, User -> User.getAge() > 30);
    // List<User> users = filterUser(userList, (e) -> e.getAge() > 30);

    users.forEach(System.out::println);
}

有的同学可能感觉还不够过瘾,下面接下来看优化方式四:Stream API:

// 优化方式四:Stream API
@Test
 public void test7() {

     userList.stream().filter(User -> User.getAge() > 30).forEach(System.out::println);

     System.out.println("-------------------------------------");

     List<User> users = userList.stream().filter(User -> "女".equals(User.getGender())).collect(Collectors.toList());
     users.forEach(System.out::println);
 }

看到这段代码,是不是感觉很神奇,前面写的什么策略类呀,筛选方法啥的都可以不用要了,使用Stream API,一行代码搞定。

在这里我们先带入Stream API,简单使用了一下,此处不做过多讲解,在后面会再详细介绍。

OK,上面我们集合实际案例介绍了lambda的基本使用,下面我们来介绍一下lambda的语法。

语法介绍

Lambda表达式在Java 语言中引入了一个新的语法元素和操作符。这个操作符为-> ,该操作符被称为Lambda 操作符或剪头操作符。它将Lambda分为两个部分:
左侧:指定了Lambda表达式需要的所有参数
右侧:指定了Lambda体,即Lambda表达式要执行的功能。

  1. 语法格式一:无参数,无返回值:() -> System.out.println("Hello Lambda");
@Test
public void test1(){

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            System.out.println("Hello World");
        }
    };
    runnable.run();

    System.out.println("--------------------------------");

    Runnable runnable1 = () -> System.out.println("Hello Lambda");
    runnable1.run();
}
  1. 语法格式二:有一个参数,无返回值:(e) -> System.out.println(e);
@Test
public void test2(){
    Consumer<String> consumer = (e) -> System.out.println(e);
    consumer.accept("语法格式二:有一个参数,无返回值");
}
  1. 语法格式三:有一个参数时,小括号可以省略不写:e -> System.out.println(e);
@Test
public void test3(){
    Consumer<String> consumer = e -> System.out.println(e);
    consumer.accept("语法格式二:有一个参数时,小括号可以省略不写");
}
  1. 语法格式四:多个参数,有返回值,lambda体中有多条语句
@Test
public void test4(){
    Comparator<Integer> comparable = (x, y) -> {
        System.out.println("多个参数,有返回值,lambda体中有多条语句");
        return Integer.compare(x,y);
    };
}
  1. 语法格式五:多个参数,有返回值,lambda体中有一条语句,打括号和return可以不写
@Test
public void test5(){
     Comparator<Integer> comparable = (x, y) -> Integer.compare(x,y);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值