Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Lambda 表达式带来的复杂性的破解之道

Lambda 表达式带来的复杂性的破解之道

作者头像
明明如月学长
修改于 2021-11-29 03:19:08
修改于 2021-11-29 03:19:08
76700
代码可运行
举报
运行总次数:0
代码可运行

一、背景

Java 8 的 Lambda 表达式已经不再是“新特性”。

曾经很多人抵触 Lambda 表达式,现在几乎也成了标配。

实际开发中最常见的是,很多人使用 Stream 来处理集合类。

但是由于 Lambda 表达式的滥用,代码可读性会变差,那么该如何解决?

本文会讨论一下这个问题,并给出自己的几个解决办法。

二、看法

对于 Lambda 表达式或者 Stream 的看法不尽一致。

2.1 支持

使用 Lambda 表达式可以减少类或者方法的常见。

使用 Stream 可以享受链式编程的乐趣。

有些人看别人都在用,似乎有些高端,或者担心自己被淘汰也跟着大量使用。

2.2 反对

有些人对 lambda 表达式持反对意见。

他们认为大量使用 lambda 表达式写出的代码不容易理解

还有的团队老人比较多,不太容易接受新的事物,不提倡使用 Lambda 表达式。

如:

Stream 的广泛使用带来了很多样板方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
List<String> tom = dogs.stream().filter(dog -> dog.getName().startsWith("tom")).map(dog -> dog.getName().toLowerCase()).collect(Collectors.toList());

甚至经常有人会在 Stream 的 map 函数中写大量转换代码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import lombok.Data;

@Data
public class DogDO {
    private String name;

    private String nickname;

    private String address;

    private String owner;

}

DogVO 和 DogDO 结构相同。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   List<DogVO> result = dogs.stream().filter(dog -> dog.getName().startsWith("tom")).map(dog -> {
            DogVO dogVO = new DogVO();
            dogVO.setName(dog.getName());
            dogVO.setAddress(dog.getAddress());
            dogVO.setOwner(dog.getOwner());
            return dogVO;
        }).collect(Collectors.toList());

更有甚者直接将整个 Stream 表达结果当做参数传入方法中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   result.addAll(dogs.stream().filter(dog -> dog.getName().startsWith("tom")).map(dog -> {
            DogVO dogVO = new DogVO();
            dogVO.setName(dog.getName());
            dogVO.setAddress(dog.getAddress());
            dogVO.setOwner(dog.getOwner());
            return dogVO;
        }).collect(Collectors.toList()));

当一个方法中大量出现上述现象时,代码就没法读了。

还有人担心 Stream 会带来一些副作用。

三、底层原理

参见我的另外一篇文章

《深入理解 Lambda 表达式》

四、建议

Lambda 可以简化代码,但是要把握度,如果滥用 lambda 表达式,代码可读性会很差。

4.1 使用方法引用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 List<String> names = new LinkedList<>();
names.addAll(users.stream().map(user -> user.getName()).filter(userName -> userName != null).collect(Collectors.toList()));
names.addAll(users.stream().map(user -> user.getNickname()).filter(nickname -> nickname != null).collect(Collectors.toList()));

可以优化为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
List<String> names = new LinkedList<>();
        names.addAll(users.stream().map(User::getName).filter(Objects::nonNull).collect(Collectors.toList()));
        names.addAll(users.stream().map(User::getNickname).filter(Objects::nonNull).collect(Collectors.toList()));

4.2 复杂代码抽取出来

对于部分复杂逻辑、对于部分需要复用的逻辑,建议封装成独立的类。

Stream参数中常用的 java.util.function 包下的 PredicateFunctionConsumer 类和 Comparator 等。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   result.addAll(dogs.stream().filter(dog -> dog.getName().startsWith("tom")).map(dog -> {
            DogVO dogVO = new DogVO();
            dogVO.setName(dog.getName());
            dogVO.setAddress(dog.getAddress());
            dogVO.setOwner(dog.getOwner());
            return dogVO;
        }).collect(Collectors.toList()));

改造如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.function.Function;

public class DogDO2VOConverter implements Function<DogDO, DogVO> {
    @Override
    public DogVO apply(DogDO dogDO) {
        DogVO dogVO = new DogVO();
        dogVO.setName(dogDO.getName());
        dogVO.setAddress(dogDO.getAddress());
        dogVO.setOwner(dogDO.getOwner());
        return dogVO;
    }
}

改造

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 result.addAll(dogs.stream().filter(dog -> dog.getName().startsWith("tom")).map(new DogDO2VOConverter()).collect(Collectors.toList()));

或者定义静态方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class DogDO2VOConverter {
    
    public static DogVO toVo(DogDO dogDO) {
        DogVO dogVO = new DogVO();
        dogVO.setName(dogDO.getName());
        dogVO.setAddress(dogDO.getAddress());
        dogVO.setOwner(dogDO.getOwner());
        return dogVO;
    }
}

直接使用方法调用即可

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        result.addAll(dogs.stream().filter(dog -> dog.getName().startsWith("tom")).map(DogDO2VOConverter::toVo).collect(Collectors.toList()));

4.3 不要将stream 操作放在方法参数中

正如上面的代码一样

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        result.addAll(dogs.stream().filter(dog -> dog.getName().startsWith("tom")).map(DogDO2VOConverter::toVo).collect(Collectors.toList()));

很多人写代码时,喜欢将 Stream 操作放到方法参数中来节省一个局部变量。

我个人非常反对这种行为,这样做极大降低了代码的可读性。

我们应该将 Stream 的操作定义具有明确含义的返回值,然后再使用。

如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   List<DogVO> toms = dogs.stream().filter(dog -> dog.getName().startsWith("tom")).map(DogDO2VOConverter::toVo).collect(Collectors.toList());
  result.addAll(toms);

4.4 Lambda 表达式不宜过长

很多人尝到了链式编程的甜头以后,总喜欢把代码写的很长。

如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 Optional.ofNullable(dogs).orElse(new ArrayList<>()).stream().filter(dog -> dog.getName().startsWith("tom")).map(DogDO2VOConverter::toVo).collect(Collectors.toList()));

但看这一句代码都很费劲,当一个函数中出现大量这种代码时,简直要吐血。

对于这种长的 Lambda 表达式写法,建议尽可能拆分出来。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    List<Dog> dogs = Optional.ofNullable(dogs).orElse(new ArrayList<>());
        List<String> toms = dogs.stream().filter(dog -> dog.getName().startsWith("tom")).map(DogDO2VOConverter::toVo).collect(Collectors.toList()))

然后进一步将 dogs.stream 这部分逻辑封装为子函数。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    List<Dog> dogs = Optional.ofNullable(dogs).orElse(new ArrayList<>());
        List<String> toms = getDogNamesStartWithTom(dogs)

这样就比较清晰易懂。

4.5 样板方法使用泛型封装

如果你发现你的项目中大量使用 Lambda,而且有很多代码的逻辑非常相似,可以考虑使用泛型封装工具类来简化代码。

下面给出两个简单的示例。

4.5.1 Stream 对象转换

实际开发中类似先过滤后转换的代码非常多:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
List<DogVO> vos = dogs.stream().map(DogDO2VOConverter::toVo).collect(Collectors.toList())

实际上这种写法习以为常,但一个方法出现多次这种写法就非常不宜读。

封装成工具类之后就比较简洁:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 List<DogVO> vos = MyCollectionUtils.convert(dogs,DogDO2VOConverter::toVo);

工具类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MyCollectionUtils {

    public static <S, T> List<T> convert(List<S> source, Function<S, T> function) {

        if (CollectionUtils.isEmpty(source)) {
            return new ArrayList<>();
        }

        return source.stream().map(function).collect(Collectors.toList());
    }

    public static <S, T> List<T> convert(List<S> source, Predicate<S> predicate, Function<S, T> function) {

        if (CollectionUtils.isEmpty(source)) {
            return new ArrayList<>();
        }

        return source.stream().filter(predicate).map(function).collect(Collectors.toList());
    }
}

通过将常见的样板方法封装成工具类,可以极大简化使用时的代码。

4.5.2 Spring 策略模式案例

《巧用 Spring 自动注入实现策略模式升级版》 中提到,如下案例:

定义接口

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface Handler {

    String getType();

    void someThing();
}

VIP 用户实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import org.springframework.stereotype.Component;

@Component
public class VipHandler implements Handler{
    @Override
    public String getType() {
        return "Vip";
    }

    @Override
    public void someThing() {
        System.out.println("Vip用户,走这里的逻辑");
    }
}

普通用户实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class CommonHandler implements Handler{

    @Override
    public String getType() {
        return "Common";
    }

    @Override
    public void someThing() {
        System.out.println("普通用户,走这里的逻辑");
    }
}

模拟 Service 中使用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Service
public class DemoService implements ApplicationContextAware {


    private Map<String, List<Handler>> type2HandlersMap;

    public void test(){
      String type ="Vip";
      for(Handler handler : type2HandlersMap.get(type)){
          handler.someThing();;
      }
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

        Map<String, Handler> beansOfType = applicationContext.getBeansOfType(Handler.class);
        beansOfType.forEach((k,v)->{
            type2HandlersMap = new HashMap<>();
            String type =v.getType();
            type2HandlersMap.putIfAbsent(type,new ArrayList<>());
            type2HandlersMap.get(type).add(v);
        });
    }
}

其中 setApplicationContext 里面的代码非常相似。

可以编写工具类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import org.apache.commons.collections4.MapUtils;
import org.springframework.context.ApplicationContext;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

public class BeanStrategyUtils {

// 构造type 到多个 bean 的映射
  public static <K,B> Map<K, List<B>> buildTypeBeansMap(ApplicationContext applicationContext, Class<B> beanClass, Function<B,K> keyFunc) {
        Map<K, List<B>> result = new HashMap<>();

        Map<String, B> beansOfType = applicationContext.getBeansOfType(beanClass);
       if(MapUtils.isEmpty(beansOfType)){
           return result;
       }

        for(B bean : beansOfType.values()){
            K type = keyFunc.apply(bean);
            result.putIfAbsent(type,new ArrayList<>());
            result.get(type).add(bean);
        }
        return result;
    }

// 构造type 到单个 bean 的映射
    public static <K,B> Map<K, B> buildType2BeanMap(ApplicationContext applicationContext, Class<B> beanClass, Function<B,K> keyFunc) {
        Map<K, B> result = new HashMap<>();

        Map<String, B> beansOfType = applicationContext.getBeansOfType(beanClass);
        if(MapUtils.isEmpty(beansOfType)){
            return result;
        }

        for(B bean : beansOfType.values()){
            K type = keyFunc.apply(bean);
            result.put(type,bean);
        }
        return result;
    }
}

改造后

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Service
public class DemoService  implements ApplicationContextAware {

    private Map<String, List<Handler>> type2HandlersMap;

    public void test(){
        String type ="Vip";
        for(Handler handler : type2HandlersMap.get(type)){
            handler.someThing();;
        }
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        type2HandlersMap = BeanStrategyUtils.buildTypeBeansMap(applicationContext,Handler.class, Handler::getType);
    }
}

很多人可能会说,写工具方法也很花时间呢。

但是,写工具方法之后,代码重复率降低;代码更加简洁,可读性提高;后续类似逻辑都可以实现代码复用,开发效率也提高了;一举多得。

4.6 使用加强包

前面讲到了,可以通过封装工具类来减少 Lambda 代码的复杂性。

此外,我们还可以考虑使用一些加强包来解决这个问题。

4.6.1 StreamEx

StreamEx

Maven 依赖

https://mvnrepository.com/artifact/one.util/streamex

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
    <groupId>one.utilgroupId>
    <artifactId>streamexartifactId>
    <version>0.8.0version>
dependency>

Java 8 写法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 Map<Role, List<User>> role2users = users.stream().collect(Collectors.groupingBy(User::getRole));

StreamEx 写法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Map<Role, List<User>> role2users = StreamEx.of(users).groupingBy(User::getRole);

前面的案例

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
List<DogVO> vos = dogs.stream().map(DogDO2VOConverter::toVo).collect(Collectors.toList())

就可以改为

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 List<DogVO> vos = StreamEx.of(dogs).map(DogDO2VOConverter::toVo).toList();

4.6.2 vavr

vavr

用户文档:https://docs.vavr.io/

Maven 依赖

https://mvnrepository.com/artifact/io.vavr/vavr

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
    <groupId>io.vavrgroupId>
    <artifactId>vavrartifactId>
    <version>1.0.0-alpha-4version>
dependency>

Java 8 中的写法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// = ["1", "2", "3"] in Java 8
Arrays.asList(1, 2, 3)
      .stream()
      .map(Object::toString)
      .collect(Collectors.toList())

vavr 中的写法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// = Stream("1", "2", "3") in Vavr
Stream.of(1, 2, 3).map(Object::toString)

4.7 有些场景不用 Lambda 表达式

如果你发现某个函数里使用 Lambda 过多时(实际工作中,发现会有人一个函数里一半以上都是 lambda 表达式,非常头疼),可以考虑将部分不容易懂的 Lambda 写法改为普通写法,通常可读性会大大提高。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
List<String> names = new LinkedList<>();
        names.addAll(users.stream().map(User::getName).filter(Objects::nonNull).collect(Collectors.toList()));
        names.addAll(users.stream().map(User::getNickname).filter(Objects::nonNull).collect(Collectors.toList()));

优化为

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 List<String> names = new LinkedList<>();
        for(User user : users) {
            String name = user.getName();
            if(name!= null ){
                names.add(name);
            }
            
            String nickname = user.getNickname();
            if(nickname != null){
                names.add(nickname);
            }
        }

虽然代码更长,但是更容易看懂。

还可将该部分逻辑封装为一个子函数并给一个有意义的命名。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  /**
     * 获取名称和昵称
     */
    private  List<String> getNamesAndNickNames(List<User> users) {
        List<String> names = new LinkedList<>();
        for (User user : users) {
            String name = user.getName();
            if (name != null) {
                names.add(name);
            }

            String nickname = user.getNickname();
            if (nickname != null) {
                names.add(nickname);
            }
        }
        return names;
    }

使用时直接调用即可:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
List<String> names = getNamesAndNickNames(users);

这样外层函数可以明确知道这部分逻辑的意图,压根不需要看这么多代码,可读性大大提高。

五、思考

过犹不及,我们使用 Lambda 表达式时,一定不要忽略可读性。

Lambda 表达式没有错,错在很多人滥用 Lambda 表达式。

我们在编码过程中要注意做好权衡,掌握好度。

本文简单谈了 Lambda 表达式的利弊,给出自己的几点破解之法。

希望对大家有帮助。

当然,可能还有很多解决办法,欢迎留言补充。

希望大家能够努力做个有追求的程序员。

创作不易,如果本文对你有帮助,你的支持和鼓励,是我创作的最大动力。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/11/27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
深入理解 Lambda 表达式
Java 8 的 Lambda 表达式已经不再是“新特性”。 现在很多人工作中会使用 Lambda 表达式。 但是,你是否真正理解 Lambda 表达式的底层原理?
明明如月学长
2021/11/29
4240
深入理解 Lambda 表达式
深入理解 Lambda 表达式
Java 8 的 Lambda 表达式已经不再是“新特性”。 现在很多人工作中会使用 Lambda 表达式。 但是,你是否真正理解 Lambda 表达式的底层原理?
明明如月学长
2022/02/15
3960
深入理解 Lambda 表达式
Lambda【1】-- List相关Lambda表达式使用(上篇)
Lambda在jdk1.8里面已经很好用了,在这里不讲底层的实现,只有简单的用法,会继续补全。
秦怀杂货店
2020/12/26
9310
Lambda表达式和函数式编程
迭代器内第一个参数为初始值,第二个参数为一个lambda表达式,因为这个循环是个死循环所以这边limit了前10个元素
后端码匠
2021/04/02
1.3K0
Java 8 Lambda / Stream 基本使用再练【超详细小白向教程】
Java 8 引入了 Lambda 表达式与 Stream API,这不仅大幅减少了冗余代码,也让 Java 代码更简洁、函数式、更具表达力。对于刚接触 Java 8 的开发者来说,这两个新特性看起来有点“陌生”,但只要掌握核心语法和典型用法,就能迅速提升编码效率。
默 语
2025/04/08
2620
Java8特性详解 lambda表达式(二):流式处理中的lambda
要讲 Stream ,那就不得不先说一下它的左膀右臂 Lambda 和方法引用,你用的 Stream API 其实就是函数式的编程风格,其中的「函数」就是方法引用,「式」就是 Lambda 表达式。
程序员黄小斜
2021/12/13
8210
5万字长文:Stream和Lambda表达式最佳实践-附PDF下载
今天要讲的Stream指的是java.util.stream包中的诸多类。Stream可以方便的将之前的结合类以转换为Stream并以流式方式进行处理,大大的简化了我们的编程,Stream包中,最核心的就是interface Stream
程序那些事
2020/07/28
8390
5万字长文:Stream和Lambda表达式最佳实践-附PDF下载
Java中的集合转换(lambda表达式)
        在Java应用中进行集合对象间的转换是非常常见的事情,有时候在处理某些任务时选择一种好的数据结构往往会起到事半功倍的作用,因此熟悉每种数据结构并知道其特点对于程序员来说是非常重要的,而只知道这些是不够的,有时候你需要一个Map来处理数据,而此时你手中只有一个List,此时知道如何将List转为Map就非常重要了,而只知道for循环将List转为Map这就太Low了,JDK1.8 吸收了许多函数式编程的思想,其中的lambda表达式不仅功能强大,而且减少了很多不必要的代码,本文不是介绍lambda表达式的,主要是利用lambda表达式进行Java中结合的转换,当然lambda表达式的使用往往离不开JDK1.8 的stream类,本文主要使用lambda表达式和stream类来实现Java中集合的转换,也会涉及到利用stream对数据进行的一些处理。
Tyan
2022/05/09
8400
掌握Java 8新特性:Lambda表达式与Stream API详解
大家好,我是默语,擅长全栈开发、运维和人工智能技术。在本篇博客中,我将详细介绍Java 8中的两大核心新特性:Lambda表达式和Stream API。这些特性不仅简化了代码编写,还提高了程序的可读性和性能。通过深入的研究和代码示例,希望能帮助大家更好地掌握这些新特性,提升Java编程水平。关键词:Java 8、Lambda表达式、Stream API、新特性、代码示例。
默 语
2024/11/22
1030
盘点java8 stream中隐藏的函数式接口
所谓的函数式接口指的是只定义一个抽象方法的接口。接口类常用这个注解@FunctionalInterface表明:
shigen
2024/09/01
1540
盘点java8 stream中隐藏的函数式接口
Java8 新特性 -- Lambda 表达式的常规用法
后两种可以这样理解:“::” 是方法引用操作符,传递的是方法的引用,在接口调用唯一方法的时候就是在调用传递进来的方法引用,所以在以上语法的基础上,只要保持返回值和参数完全一致就能将方法传递进去。
啵啵肠
2023/11/20
1400
常用Lamda表达式
我们在使用lamda表达式排序的时候,很多时候考虑到空指针可能会选择传统的方式,lamda实际上也有防止空指针的排序。
全栈程序员站长
2022/06/30
2950
常用Lamda表达式
Java里面的10个Lambda表达式必须掌握,提高生产力
Lambda表达式是一种在现代编程语言中越来越常见的特性,可以简化代码、提高生产力。这篇文章将介绍10个必须掌握的Lambda表达式,这些表达式涵盖了在实际编程中经常用到的常见场景,例如列表操作、函数组合、条件筛选等。通过学习这些Lambda表达式,你将更加深入地理解函数式编程的思想,能够更加高效地编写代码。
正在走向自律
2024/12/18
2040
Java里面的10个Lambda表达式必须掌握,提高生产力
java8 最大的特性:Lambda表达式,即函数式编程
java8最大的特性就是引入Lambda表达式,即函数式编程,可以将行为进行传递。总结就是:使用不可变值与函数,函数对不可变值进行处理,映射成另一个值。
二哥聊运营工具
2021/12/17
5380
java8 最大的特性:Lambda表达式,即函数式编程
Java8 Lambda表达式与Stream API (二): Stream API的使用你要知道的Java8 匿名内部类、函数式接口、lambda表达式与Stream API都在这里
你要知道的Java8 匿名内部类、函数式接口、lambda表达式与Stream API都在这里 转载请注明出处 https://cloud.tencent.com/developer/user/1605429 本文主要讲解Java8 Stream API,但是要讲解这一部分需要匿名内部类、lambda表达式以及函数式接口的相关知识,本文将分为两篇文章来讲解上述内容,读者可以按需查阅。 Java 匿名内部类、lambda表达式与函数式接口 Java Stream API 本文是本系列文章的第二篇,主要讲解St
WWWWDotPNG
2018/04/10
1.3K0
Java8 Lambda表达式与Stream API (二): Stream API的使用你要知道的Java8 匿名内部类、函数式接口、lambda表达式与Stream API都在这里
JDK8新特性
文章目录 1. JDk8新特性 1.1. 函数式编程 1.1.1. 集合的foreach 1.1.2. lambda表达式轻松创建接口实例 1.1.3. 接口的默认方法和静态方法 1.1.4. Stream 1.1.4.1. filter 1.1.4.2. sorted 1.1.4.3. 查找和匹配 1.1.4.4. 归约 1.1.4.4.1. map 1.1.4.4.2. reduce 1.1.4.5. 分组 1.2. Optional 1.3. Collectors 1.3.1. toMap 1.3
爱撒谎的男孩
2019/12/31
8000
Java8特性详解 lambda表达式(一):使用篇
在 Java 8之前,一个实现了只有一个抽象方法的接口的匿名类看起来更像Lambda 表达式。下面的代码中,anonymousClass方法调用waitFor方法,参数是一个实现接口的Condition类,实现的功能为,当满足某些条件,Server 就会关闭。 下面的代码是典型的匿名类的使用。
程序员黄小斜
2021/12/13
5010
Java Stream的使用
流是Java API的新成员,它允许你以声明性方式处理数据集合(通过查询语句来表达,而不是临时编写一个实现)
终码一生
2024/05/10
1450
Java Stream的使用
Java的函数式接口以及Lambda表达式
在java中,大家肯定使用过lambda表达式吧,这是适用于函数式接口的一种便捷写法。
半月无霜
2023/03/03
4740
Java的函数式接口以及Lambda表达式
Lambda表达式:简介、语法和用法
Lambda表达式是Java 8中引入的一个重要特性,它允许开发者以更加简洁的方式编写函数式代码。在本文中,我们将深入探讨Lambda表达式的概念、语法和用法,并为每个实例提供代码演示,同时对比与传统方法的区别和优势。
默 语
2024/11/20
2080
推荐阅读
相关推荐
深入理解 Lambda 表达式
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验