`Streams.concat` functions as expected when its arguments are finite streams.
If we concat two streams: the first is finite and the second is infinite, then obviously we get an infinite stream. But we can iterate over a limited number of elements. This is the scenario where the program hangs.

```java
import com.google.common.collect.Streams;

import java.util.PrimitiveIterator;
import java.util.stream.IntStream;

public class MyMain {
    public static void main(String[] args) {

        IntStream stream123 = IntStream.of(1, 2, 3);
        IntStream stream4567 = IntStream.of(4, 5, 6, 7);
        IntStream stream1234567 = Streams.concat(stream123, stream4567);
        printFirstElements(stream1234567, 5);
        // output:
        // 1
        // 2
        // 3
        // 4
        // 5



        IntStream streamInfinite99 = IntStream.generate(() -> 99);
        printFirstElements(streamInfinite99, 3);
        // output:
        // 99
        // 99
        // 99

        IntStream stream123AndThenInfinite77 = Streams.concat(IntStream.of(1, 2, 3), IntStream.generate(() -> 77));
        printFirstElements(stream123AndThenInfinite77, 5);
        // output:
        // 1
        // 2
        // 3
        // and then program hangs
    }

    static void printFirstElements(IntStream stream, int count) {
        int counter = 0;
        for (PrimitiveIterator.OfInt iterator = stream.iterator(); iterator.hasNext(); ) {
            Integer next = iterator.next();
            System.out.println(next);
            counter++;
            if (counter == count) {
                break;
            }
        }
    }
}
```
}
  /**
   * Returns a supplier which caches the instance retrieved during the first call to {@code get()}
   * and returns that value on subsequent calls to {@code get()}. See: <a
   * href="http:en.wikipedia.org/wiki/Memoization">memoization</a>
   *
   * <p>The returned supplier is thread-safe. The delegate's {@code get()} method will be invoked at
   * most once unless the underlying {@code get()} throws an exception. The supplier's serialized
   * form does not contain the cached value, which will be recalculated when {@code get()} is called
   * on the reserialized instance.
   *
   * <p>When the underlying delegate throws an exception then this memoizing supplier will keep
   * delegating calls until it returns valid data.
   *
   * <p>If {@code delegate} is an instance created by an earlier call to {@code memoize}, it is
   * returned directly.
   */
  public static <T> Supplier<T> memoize(Supplier<T> delegate) {
    if (delegate instanceof NonSerializableMemoizingSupplier
        || delegate instanceof MemoizingSupplier) {
      return delegate;
    }
    return delegate instanceof Serializable
        ? new MemoizingSupplier<T>(delegate)
        : new NonSerializableMemoizingSupplier<T>(delegate);
  }
  @VisibleForTesting
  static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
    final Supplier<T> delegate;
    transient volatile boolean initialized;