Is there a Java equivalent to C#'s 'yield' keyword?

Viewed 38183

I know there is no direct equivalent in Java itself, but perhaps a third party?

It is really convenient. Currently I'd like to implement an iterator that yields all nodes in a tree, which is about five lines of code with yield.

7 Answers

I just published another (MIT-licensed) solution here, which launches the producer in a separate thread, and sets up a bounded queue between the producer and the consumer, allowing for buffering, flow control, and parallel pipelining between producer and consumer (so that the consumer can be working on consuming the previous item while the producer is working on producing the next item).

You can use this anonymous inner class form:

Iterable<T> iterable = new Producer<T>(queueSize) {
    @Override
    public void producer() {
        produce(someT);
    }
};

for example:

for (Integer item : new Producer<Integer>(/* queueSize = */ 5) {
    @Override
    public void producer() {
        for (int i = 0; i < 20; i++) {
            System.out.println("Producing " + i);
            produce(i);
        }
        System.out.println("Producer exiting");
    }
}) {
    System.out.println("  Consuming " + item);
    Thread.sleep(200);
}

Or you can use lambda notation to cut down on boilerplate:

for (Integer item : new Producer<Integer>(/* queueSize = */ 5, producer -> {
    for (int i = 0; i < 20; i++) {
        System.out.println("Producing " + i);
        producer.produce(i);
    }
    System.out.println("Producer exiting");
})) {
    System.out.println("  Consuming " + item);
    Thread.sleep(200);
}

I'd also suggest if you're already using RXJava in your project to use an Observable as a "yielder". It can be used in a similar fashion if you make your own Observable.

public class Example extends Observable<String> {

    public static void main(String[] args) {
        new Example().blockingSubscribe(System.out::println); // "a", "b", "c", "d"
    }

    @Override
    protected void subscribeActual(Observer<? super String> observer) {
        observer.onNext("a"); // yield
        observer.onNext("b"); // yield
        observer.onNext("c"); // yield
        observer.onNext("d"); // yield
        observer.onComplete(); // finish
    }
}

Observables can be transformed into iterators so you can even use them in more traditional for loops. Also RXJava gives you really powerful tools, but if you only need something simple then maybe this would be an overkill.

// Java code for Stream.generate()
// to generate an infinite sequential
// unordered stream
import java.util.*;
import java.util.stream.Stream;
  
class GFG {
      
    // Driver code
    public static void main(String[] args) {
      
    // using Stream.generate() method 
    // to generate 5 random Integer values
    Stream.generate(new Random()::nextInt)
      .limit(5).forEach(System.out::println); 
    }
}

From here.

Related