Java8流式传输类层次结构 [英] Java8 Streaming a class hierarchy

查看:23
本文介绍了Java8流式传输类层次结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在慢慢学习 Java 8 的新特性,我正在尝试找到一种将类层次结构(从子级到父级)作为流处理的方法.

I am slowly learning the new Java 8 features and I am trying to find a way to process a class hierarchy (from child to parent) as a stream.

例如在类或其父类上查找注释.

For instance find an annotation on a class or it's parents.

在 Java 8 之前,我会这样做:

Before Java 8, I would have done it this way :

public static <T extends Annotation> T getAnnonationOn(Class<?> type, Class<T> annType) {
    Class<?> t = type;
    T annot = null;
    while (t != null && annot == null) {
        annot = t.getAnnotation(annType);
        t = t.getSuperclass();
    }
    return annot;
}

现在我希望用一种更函数式编程"的方式来实现.我找不到比使用以下递归连接流更好的方法:

Now I wish to do it with a more "functional programming" way. I could not find a better way than concatenate streams with a recursive like follow :

import java.lang.annotation.Annotation;
import java.util.stream.Stream;

public static <T extends Annotation> T getAnnonationOn(Class<?> type, Class<T> annType) {
    return ClassIterator.streamSuperclass(type)
        .map(t -> t.getAnnotation(annType))
        .filter(a -> a != null)
        .findFirst()
        .orElse(null);
}

public static class ClassIterator {
    public static Stream<Class<?>> streamSuperclass(Class<?> type) {
        if (type.getSuperclass() != null) {
            return Stream.concat(Stream.of(type), Stream.of(type.getSuperclass()).flatMap(ClassIterator::streamSuperclass));
        }
        return Stream.of(type);
    }
}

但我对解决方案不太满意.虽然我没有对其进行基准测试,但我认为流连接非常麻烦且性能不佳.

But I am not quite satisfied of the solution. Although I did not benchmark it I think the stream concatenation is quite cumbersome and under performant.

有没有更好的方法将递归变成流?

Is there a better way to turn a recursive into a stream ?

推荐答案

在 Java 9 中,您可能会使用

In Java 9, you would probably use

public static Stream<Class<?>> streamSuperclass(Class<?> type) {
    return Stream.iterate(type, Objects::nonNull, Class::getSuperclass);
}

但在 Java 8 中,此功能不可用,因此您可以求助于手动实现 Stream:

but in Java 8, this feature is not available, so you may resort to implement the Stream manually:

public static Stream<Class<?>> streamSuperclass(Class<?> type) {
    return StreamSupport.stream(
        new Spliterators.AbstractSpliterator<Class<?>>(100L,
            Spliterator.ORDERED|Spliterator.IMMUTABLE|Spliterator.NONNULL) {
            Class<?> current = type;
            public boolean tryAdvance(Consumer<? super Class<?>> action) {
                if(current == null) return false;
                action.accept(current);
                current = current.getSuperclass();
                return true;
            }
        }, false);
}

请注意,这将从最具体的类型流向 java.lang.Object.如果您希望顺序从 Object 到最具体的一个,则没有办法首先收集元素,无论是递归还是迭代,都不是那么重要,但是 Stream.concat 确实是性能最低的变体.你可以简单地使用

Note that this will stream from the most specific type towards java.lang.Object. If you want the order to be from Object to the most specific one, there is no way around gathering the elements first, whether recursive or iterative, is not so important, but Stream.concat is indeed the least performance variant. You can simply use

public static Stream<Class<?>> streamSuperclass(Class<?> type) {
    return reverse(Stream.<Class<?>>builder(), type, Class::getSuperclass).build();
}
private static <T> Stream.Builder<T> reverse(
        Stream.Builder<T> builder, T t, UnaryOperator<T> op) {
    return t==null? builder: reverse(builder, op.apply(t), op).add(t);
}

迭代变体也不错:

public static Stream<Class<?>> streamSuperclass(Class<?> type) {
    List<Class<?>> l=new ArrayList<>();
    for(; type!=null; type=type.getSuperclass()) l.add(type);
    Collections.reverse(l);
    return l.stream();
}

对于像典型类层次结构这样小的流,ArrayList 并不比 Stream.Builder 差,对于非常大的流,使用递归填充构建器可能也不是最好的解决方案……

For streams as small as a typical class hierarchy, an ArrayList is not worse than a Stream.Builder and for very large streams, filling the builder using a recursion might not be the best solution either…

这篇关于Java8流式传输类层次结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆