代码之家  ›  专栏  ›  技术社区  ›  Punter Vicky

在不使用条件块的情况下重构代码

  •  0
  • Punter Vicky  · 技术社区  · 3 年前

    我希望避免多次 if-else 条件有没有更简洁的方法来编写下面的代码?

    private Set<String> getValues(Optional<String> one, Optional<String> two) {
        if (one.isPresent() && two.isPresent()) {
            return ImmutableSet.of(one.get(), two.get());
        } else if (one.isPresent()) {
            return ImmutableSet.of(one.get());
        } else {
            return two.isPresent() ? ImmutableSet.of(two.get()) : ImmutableSet.of();
        }
    }
    
    0 回复  |  直到 3 年前
        1
  •  10
  •   Beri    3 年前

    最简单的解决方案是使用 Optional.stream() ,jdk9+:

       private Set<String> getValuesJdk9(Optional<String> one, Optional<String> two) {
           return Stream.concat(one.stream(), two.stream())
                  .collect(Collectors.toUnmodifiableSet());
        }
    

    你可以阅读更多 here

    如果您仍在使用JDK8:

     private Set<String> getValuesJdk8(Optional<String> one, Optional<String> two) {
           return Stream.of(one, two)
                  .filter(Optional::isPresent)
                  .map(Optional::get)
                  .collect(Collectors.toUnmodifiableSet());
        }
    

    还有一个极端的版本,当你可以传递任意数量的参数时

       private Set<String> getAllValues(Optional<String>... options) {
            return Arrays.stream(options).flatMap(Optional::stream)
                    .collect(Collectors.toUnmodifiableSet());
        }
    
        2
  •  1
  •   Alexander Ivanchenko    3 年前

    TL;DR

    根据文件收集器 Collectors.toSet() ( 用于另一个答案 )给予 对返回的可变性的保证 Set 。目前,它提供 可变的 通用实施- HashSet

    如果您需要 不变的 设置 以下是选项:

    • 有几种方法可以生成 Unmodifiable Set JDK提供的。

    • 你可以利用番石榴的功能 ImmutableSet 包括…在内 Collector ImmutableSet.toImmutableSet()

    质疑问题陈述

    首先,这是一个 气馁的 练习传球 Optional s

    这是引用 answer 作者:Brian Goetz,Java语言架构师,规范了 可选择的 :

    我们的意图是提供 有限机构 对于 图书馆 方法返回类型 需要有一条明确的途径 表示“没有结果”,而使用null表示这绝大多数 可能导致错误。

    例如,你可能永远不应该把它用于 返回结果数组或结果列表;而是返回 空数组或列表。你应该差不多 从不使用 它是一个 某物或 方法参数

    另请参阅Java和OpenJDK开发人员Stuart Marks的回答 Uses for Optional

    使用更清洁的替代品 可选择的 作为方法参数传递 可选择的 您可以提供 Supplier 属于 可选择的 并在你的方法中进行评估。

    假设你有方法 foo() bar() 返回 可选择的 ,则如果将方法签名更改为:

    getValues(Supplier<Optional<T>> first, Supplier<Optional<T>> second)
    

    然后您可以调用这样的方法: getValues(x::foo, y::bar)

    问题可以概括为:

    “将非空Optionals中的N个值收集到不可变集合中”

    番石榴 ImmutableSet.toImmutableSet()

    自从Guava发布版本 21.0 ( 它需要JDK 8作为最低版本 )你可以使用 收集器 返回者 不可变集.toImmutableSet()

    @SafeVarargs
    private static <T> Set<T> getValues(Supplier<Optional<T>>... suppliers) {
    
        return Arrays.stream(suppliers)
            .map(Supplier::get)
            .filter(Optional::isPresent)
            .map(Optional::get)
            .collect(ImmutableSet.toImmutableSet());
    }
    

    标准JDK Collectors.toUnmodifiableSet()

    出于完整性的目的,这里有一个不需要依赖关系的解决方案。

    自从Java 10收集器 toUnmodifiableSet() JDK中提供。

    @SafeVarargs
    private static <T> Set<T> getValues(Supplier<Optional<T>>... suppliers) {
    
        return Arrays.stream(suppliers)
            .map(Supplier::get)
            .filter(Optional::isPresent)
            .map(Optional::get)
            .collect(Collectors.toUnmodifiableSet());
    }