Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 Stream of Super Classes, Parent Files, Component Parents, linked list, etc

I would like to convert the following for statement to a Java 8 stream (i.e. Stream<Class<?>>). The ideal solution would be simple enough that I can easily adapt it for a variety of situations of traversing a linked list (e.g. File.getParentFile(), Component.getParent()).

  Class<?> clazz;
  Object value;

  value = ...;

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

I realize that a few lines of code to create a stream isn't going to be simpler than a single for statement. However, a stream makes the body of the for loop simpler and hence a stream is desirable.

like image 332
Nathan Avatar asked Jan 22 '16 22:01

Nathan


People also ask

What are the main components of a stream in Java 8?

A stream pipeline consists of a stream source, followed by zero or more intermediate operations, and a terminal operation. Here, we use short-circuiting operations skip() to skip first 3 elements, and limit() to limit to 5 elements from the infinite stream generated using iterate().

What are the components of a Java stream?

Stream Pipeline To perform a sequence of operations over the elements of the data source and aggregate their results, we need three parts: the source, intermediate operation(s) and a terminal operation.

What does stream () do in Java?

Introduced in Java 8, the Stream API is used to process collections of objects. A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result. A stream is not a data structure instead it takes input from the Collections, Arrays or I/O channels.

Does Java 8 streams have limited storage?

No storage. Streams don't have storage for values; they carry values from a source (which could be a data structure, a generating function, an I/O channel, etc) through a pipeline of computational steps.


2 Answers

You need a takeWhile method which will appear in JDK-9 only. Currently you can use a back-port which is available, for example, in my StreamEx library:

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

In JDK-9 just replace StreamEx with Stream.

like image 178
Tagir Valeev Avatar answered Sep 28 '22 08:09

Tagir Valeev


Here's the same code as presented in the question but implemented using a Spliterator. I am hoping someone can come up with a simpler, smarter answer.

  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);
   }
}
like image 39
Nathan Avatar answered Sep 28 '22 10:09

Nathan