Java 8流式处理中的超类、父文件、组件父级、链表等。

5
我希望将以下的for语句转化为Java 8流(即Stream<Class<?>>)。理想的解决方案应该足够简单,我可以轻松地将其应用于多种遍历链表的情况(例如File.getParentFile()Component.getParent())。
  Class<?> clazz;
  Object value;

  value = ...;

  for (clazz = value.getClass(); clazz != null; clazz = clazz.getSuperclass())
     ...

我意识到用几行代码创建流并不比一个单独的 for 语句更简单。然而,使用流可以使 for 循环体更简单,因此流是可取的。

2个回答

7

您需要一个 takeWhile 方法,它只会在JDK-9中出现。目前,您可以使用可用的后端移植版本,例如我的 StreamEx 库:

Stream<Class<?>> stream = StreamEx.iterate(value.getClass(), Class::getSuperClass)
                                  .takeWhile(Objects::nonNull);

在JDK-9中,只需将StreamEx替换为Stream

1
JDK-9还允许Stream.iterate(value.getClass(), Objects::nonNull, Class::getSuperclass) - Holger
JDK-8可以使用更简单的Stream.iterate函数,而无需转义函数。例如,递归读取Throwable causes的代码如下:Stream.iterate(ex, Throwable::getCause) - Dudelilama

1

这里是与问题中呈现的代码相同,但使用 Spliterator 实现。我希望有人能想出一个更简单、更智能的答案。

  Class<?> clazz;
  Object value;

  value = ...;

  <Class<?>>walkLinks(value.getClass(), Class::getSuperclass).
     ...


public static <T> Stream<T> walkLinks(T start, Function<T, T> next)
{
   WalkLinks<T> walker;
   Stream<T> result;

   walker = new WalkLinks<>(start, next);
   result = StreamSupport.stream(walker, false);

   return(result);
}

private static class WalkLinks<T> extends Spliterators.AbstractSpliterator<T>
{
   private final Function<T, T> m_next;
   private       T              m_value;

   public WalkLinks(T value, Function<T, T> next)
   {
      super(Long.MAX_VALUE, Spliterator.ORDERED + Spliterator.NONNULL);

      m_value = value;
      m_next  = next;
   }

   @Override
   public boolean tryAdvance(Consumer<? super T> action)
   {
      if (m_value == null)
         return(false);

      action.accept(m_value);

      m_value = m_next.apply(m_value);

      return(true);
   }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接