Поток суперклассов 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);
}
}