首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在现有Java 7代码中使用Java 8可选

在现有Java 7代码中使用Java 8可选
EN

Stack Overflow用户
提问于 2017-05-03 13:17:17
回答 4查看 1.8K关注 0票数 3

我有一个任务,需要将以下Java 8之前的代码转换为Java 8代码。下面只是一个让我很难完成的方法:

代码语言:javascript
复制
  public static List<VehicleMake> loadMatching(Region region, String nameStartsWith, VehicleLoader loader) {
    if ((nameStartsWith == null) || (region == null) || (loader == null)) {
        throw new IllegalArgumentException("The VehicleLoader and both region and nameStartsWith are required when loading VehicleMake matches");
    }
    List<VehicleMake> regionMakes = loader.getVehicleMakesByRegion(region.name());
    if (regionMakes == null) {
        return null;
    }
    List<VehicleMake> matches = new ArrayList<>(regionMakes.size());
    for (VehicleMake make : regionMakes) {
        if ((make.getName() == null) || !make.getName().startsWith(nameStartsWith)) {
            continue;
        }
        matches.add(make);
    }
    return matches;
}

我想使用Optional<T>删除null检查,而不修改以前创建的类和接口。

我尝试通过更改方法返回类型并执行以下操作开始,但编译器抛出了此错误:

Bad return type in method reference,因为VehicleMake类没有可选的实例字段。

以下是我的代码尝试:

代码语言:javascript
复制
   public static Optional<List<VehicleMake>> loadMatchingJava8(Region region, String nameStartsWith, VehicleLoader loader) {
    Optional<List<VehicleMake>> regionMakes = Optional.ofNullable(loader).ifPresent(loader.getVehicleMakesByRegion(Optional.ofNullable(region).ifPresent(region.name())));
    /*

    TODO rest of the conversion
     */
}

编辑:通过不将参数传递给方法引用,删除了flatMap并更正了代码。但是现在它不允许我将region.name()传递给getVehicleMakesByRegion()

编辑:将消费者传递给ifPresent()

代码语言:javascript
复制
Optional<List<VehicleMake>> regionMakes = Optional.ofNullable(loader).ifPresent(()-> loader.getVehicleMakesByRegion(Optional.ofNullable(region).ifPresent(()->region.name()));
EN

回答 4

Stack Overflow用户

发布于 2017-05-03 17:21:14

您可以将初始null检查替换为

代码语言:javascript
复制
Optional.ofNullable(nameStartsWith)
        .flatMap(x -> Optional.ofNullable(region))
        .flatMap(x -> Optional.ofNullable(loader))
        .orElseThrow(() -> new IllegalArgumentException(
            "The VehicleLoader and both region and nameStartsWith"
          + " are required when loading VehicleMake matches"));

但这是对API的滥用。更糟糕的是,为了在错误情况下提供一个相当无意义的异常这个可疑的目标,它浪费了资源。

与…比较

代码语言:javascript
复制
Objects.requireNonNull(region, "region is null");
Objects.requireNonNull(nameStartsWith, "nameStartsWith is null");
Objects.requireNonNull(loader, "loader is null");

这是简洁的,并将抛出一个异常,并在错误情况下提供准确的消息。它将是一个NullPointerException而不是一个IllegalArgumentException,但即使是这样的更改也会导致对实际问题的更准确的描述。

关于该方法的其余部分,我强烈建议从一开始就不要让Collectionnull。这样,您就不必测试nullgetVehicleMakesByRegion结果,也就不会自己返回null了。

但是,如果您必须使用原始逻辑,则可以使用

代码语言:javascript
复制
return Optional.ofNullable(loader.getVehicleMakesByRegion(region.name()))
               .map(regionMakes -> regionMakes.stream()
                    .filter(make -> Optional.ofNullable(make.getName())
                                            .filter(name->name.startsWith(nameStartsWith))
                                            .isPresent())
                    .collect(Collectors.toList()))
               .orElse(null);

初始代码旨在拒绝null引用,不应与用于处理null引用的实际操作混淆。

票数 4
EN

Stack Overflow用户

发布于 2017-05-03 13:53:29

我已经用Optional更新了你的代码

代码语言:javascript
复制
     public static List<VehicleMake> loadMatchingJava8(Region region, String nameStartsWith, VehicleLoader loader) {
        Optional<List<VehicleMake>> regionMakes = Optional.ofNullable(region)
                .flatMap(r -> Optional.ofNullable(loader).map(l -> l.getVehicleMakesByRegion(r.name())));

        return Optional.ofNullable(nameStartsWith)
                .map(s -> regionMakes
                    .map(Collection::stream)
                    .orElse(Stream.empty())
                    .filter(make -> make.getName() != null && make.getName().startsWith(s))
                    .collect(Collectors.toList()))
                .orElse(Collections.emptyList());
    }
票数 2
EN

Stack Overflow用户

发布于 2017-05-03 14:21:54

如果你真的想要将流控制转换成Optional,那么与你的代码保持一致的代码应该是这样的(我将代码分成两行打印):

代码语言:javascript
复制
public static Optional<List<VehicleMake>> loadMatchingJava8(Region region, 
                                                            String nameStartsWith,
                                                            VehicleLoader loader) {
    if ((nameStartsWith == null) || (region == null) || (loader == null)) {
        throw new IllegalArgumentException("The VehicleLoader and both region and " +
                "nameStartsWith are required when loading VehicleMake matches");
    }


    return Optional.ofNullable(loader.getVehicleMakesByRegion(region.name()))
            .map(makers -> makers.stream()
                    .filter((it) -> it.getName() != null
                            && it.getName().startsWith(nameStartsWith))
                    .collect(Collectors.toList()));
}

备注:您可以在此question中查看有关为什么不滥用Optional的更多信息。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43751613

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档