Поток суперклассов Java 8, родительские файлы, родительские компоненты, связанный список и т. Д.

Я хотел бы преобразовать следующее 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 ответа

Решение

Тебе необходимо takeWhile метод, который появится только в JDK-9. В настоящее время вы можете использовать бэк-порт, который доступен, например, в моей библиотеке StreamEx:

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

В JDK-9 просто замените StreamEx с Stream,

Вот тот же код, который представлен в вопросе, но реализован с использованием 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);
   }
}
Другие вопросы по тегам