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循环体更简单,因此流是可取的。

4

2 回答 2

6

您需要一个takeWhile仅出现在 JDK-9 中的方法。目前,您可以使用可用的反向端口,例如,在我的StreamEx库中:

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

在 JDK-9 中,只需替换StreamExStream.

于 2016-01-23T03:07:02.497 回答
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);
   }
}
于 2016-01-22T22:04:41.747 回答