投射可选或流的内容

时间:2018-10-31 07:35:16

标签: java casting java-8 java-stream optional

我希望不用编写自己的方法或类,而只需检查可选内容并将其转换为另一个类或具有空对象即可。

对于应用程序中的此子问题,我想将TreeNode实例的自定义用户对象强制转换为CustomUserObject,前提是TreeNode是{{ 1}}。

DefaultMutableTreeNode

我记得我需要经常以这种方式投射可选内容或流。它不流利。实际上,我希望java Optional或Stream具有执行上述步骤的强制转换方法。我不想写自己的流利的CustomOptional。我有想念吗?有什么办法可以更简单地做到这一点?

2 个答案:

答案 0 :(得分:2)

您可以依靠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

答案 1 :(得分:0)

我想出了这个用于可选

/**
 * Creates a function that tries to cast to the given class.
 * If the given argument is not an instance of the given class <code>Optional.empty()</code> is returned.
 * This function can be used in an <code>optionalObject.flatMap(Functional.cast(SomeClass.class))</code> context.
 * 
 * @author xne9645
 * @param clazz
 *        given Clazz
 * @return Returns an optional of the given class.
 * @param <X>
 *        generic input argument for the function
 * @param <T>
 *        type of the output of the function
 */
public static <X, T> Function<X, Optional<T>> cast(Class<? extends T> clazz) {
    return x -> {
        if (clazz.isInstance(x)) {
            return Optional.of(clazz.cast(x));
        }
        return Optional.empty();
    };
}

并像这样使用它:

Optional<DefaultMutableTreeNode> optParent = Optional.of(node) // optional of original node
                    .map(ProfileTreeNode::getParent) // parent of this node.
                    .flatMap(FunctionalUtil.cast(DefaultMutableTreeNode.class)); // cast to DefaultMutableTreeNode
                optParent.ifPresent(y -> y.remove(node));

对于我写的

/**
 * Creates a function that tries to cast to the given class.
 * If the given argument is not an instance of the given class an empty stream is returned.
 * This function can be used in an <code>stream.flatMap(Functional.castStream(SomeClass.class))</code> context.
 * 
 * @author xne9645
 * @param clazz
 *        given Clazz
 * @return Returns an optional of the given class.
 * @param <X>
 *        generic input argument for the function
 * @param <T>
 *        type of the output of the function
 */
public static <X, T> Function<X, Stream<T>> castStream(Class<? extends T> clazz) {
    return x -> Stream.of(x) // stream of x.
        .filter(clazz::isInstance) // check if instance
        .map(clazz::cast);
}