java - 转换可选或流的内容

标签 java casting java-8 java-stream option-type

我希望与其编写自己的方法或类,不如检查可选内容并将其转换为另一个类,或者拥有一个空对象。

对于应用程序中的这个子问题,我希望将 TreeNode 实例的自定义用户对象转换为 CustomUserObject,前提是 TreeNodeDefaultMutableTreeNode 的实例。

private Optional<CustomUserObject> getCustomUserObject(TreeNode node) {
    Optional<DefaultMutableTreeNode> optDefaultMutableTreeNode = OptionalUtil.cast(Optional.ofNullable(node), DefaultMutableTreeNode.class);
    Optional<Object> optUserObject = optDefaultMutableTreeNode.map(DefaultMutableTreeNode::getUserObject); //
    return OptionalUtil.cast(optUserObject, CustomUserObject.class);
}


/**
 * Maps the given optional, if the containing element is an instance of the given class.
 * Returns empty if the containing object is not an instance of the given class.
 * 
 * @param orgOptional
 *        given optional
 * @param clazz
 *        given class.
 * @return the resulting {@link Optional}.
 */
public static <T, X> Optional<T> cast(Optional<X> orgOptional, Class<T> clazz) {
    return orgOptional //
        .filter(clazz::isInstance) // check instance
        .map(clazz::cast); // cast
}

/**
 * Maps the given stream, if the containing element is an instance of the given class.
 * Returns empty if the containing object is not an instance of the given class.
 * 
 * @param orgStream
 *        given optional
 * @param clazz
 *        given class.
 * @return the resulting {@link Optional}.
 */
public static <T, X> Stream<T> cast(Stream<X> orgStream, Class<T> clazz) {
    return orgStream //
        .filter(clazz::isInstance) // check instance
        .map(clazz::cast); // cast
}

我记得我经常需要以这种方式转换可选值或流。它不流利。实际上我希望 java Optional 或 Stream 有一个执行上述步骤的 cast 方法。我不想自己写流利的 CustomOptional。我错过了什么吗?有没有更简单的方法来做到这一点?

最佳答案

您可以依靠返回函数的 map()/flatMap()cast 方法轻松地使其更加流畅。

对于 Optional,这很容易,因为 map() 可以通过返回 null 充当过滤器。所以只需定义:

public static <U> Function<Object, U> filterAndCast(Class<? extends U> clazz) {
    return t -> clazz.isInstance(t) ? clazz.cast(t) : null;
}

并将其用作:

Optional<Number> number = Optional.of(42L);
System.out.println(number.map(filterAndCast(Integer.class)));
System.out.println(number.map(filterAndCast(Long.class)));

输出:

Optional.empty
Optional[42]

对于流,您可以通过依赖 flatMap() 和返回空 Stream 的函数来应用或多或少相同的技巧:

public static <U> Function<Object, Stream<U>> streamFilterAndCast(Class<? extends U> clazz) {
    return t -> clazz.isInstance(t) ? Stream.of(clazz.cast(t)) : Stream.empty();
    // or alternatively
    return t -> Stream.of(t).filter(clazz::isInstance).map(clazz::cast);
}

并将其用作:

Stream.of(42L, "Hello world", 1024, 3.14)
        .flatMap(streamFilterAndCast(Number.class))
        .forEach(System.out::println);

输出:

42
1024
3.14

关于java - 转换可选或流的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53078410/

相关文章:

C libpcap API 将数据包转换为结构(令人困惑)

Java 8 : How to get a value from a list contained as a map value?

java - 局部变量必须是 final 或有效的 final

java - 是否值得使用 Selenium com.thoughtworks.selenium.Wait 类来等待? (表现)

java - 为什么我的应用程序停止工作?

casting - golang 将字符串转换为 net.IPNet 类型

c++ - 这段代码安全吗?将 std::vector<Derived*> 转换为 std::vector<Base*>

Java 8,在Lambda中转换hashmap程序

加载外部 Jar(插件架构)时 JavaFX 样式丢失

java.io.IOException : Illegal footer when importing certificate using keytool