javac#iterableenumerable

transform single element to Iterable in Java


In C#, I can transform a single element to an IEnumerable<> like this (using an extension method here):

static class Extensions
{
    static IEnumerable<T> Yield<T>(this T t)
    {
        yield return t;
    }
}

I use this when I need to input an IEnumerable<> somewhere but only have a single element, like here:

var myList = new List<string>("foo".Yield());

Is there some equivalent way to do this in Java?

I am NOT interested in actually creating an Iterable<> on the heap from an element like

List<String> myIterable = new ArrayList<String>();
myIterable.add("foo");

because I already know that kind of solution; I want to know if Java can handle enumerables/iterables as powerfully as C# (C# has Linq and yield return, Java has Streams) and lazily.


Solution

  • The easiest way is to use Collections.singleton() or Collections.singletonList().

    Collections.singleton(1);
    Collections.singletonList("");
    

    Returned collections are immutable in both cases, they are being backed only by the actual element. They are not real collections, in the sense, that they only allow iteration and other non modifying operations.

    Or you can make the implementations of Iterator and Iterable yourself, although that would be reimplementing the above to some extent (jdk already provides similar/same functionality).

    public class SingleElementIterator<T> implements Iterator<T> {
    
      private final T element;
      private boolean hasNext;
    
      public SingleElementIterator(T element) {
        this.element = element;
        this.hasNext = true;
      }
    
      @Override
      public boolean hasNext() {
        return this.hasNext;
      }
    
      @Override
      public T next() {
        if (this.hasNext) {
          this.hasNext = false;
          return this.element;
        }
        throw new NoSuchElementException();
      }
    }
    
    public class SingleElementIterable<T> implements Iterable<T> {
    
      private final T element;
    
      public SingleElementIterable(T element) {
        this.element = element;
      }
    
      @Override
      public Iterator<T> iterator() {
        return new SingleElementIterator<>(this.element);
      }
    }
    

    Example:

    public class Temp {
    
      public static void main(String[] args) {
        Iterable<String> iterable = new SingleElementIterable<>("abc");
        for (String string : iterable) {
          System.out.println(string);
        }
      }
    }