| Using `stream::iterator` to create an `Iterable` results in an `Iterable` which |
| can only be iterated once, and will throw an `IllegalArgumentException` on |
| subsequent attempts. |
| |
| The contract of `Iterable` is poorly defined, but many APIs will assume that |
| `Iterable`s allow multiple iteration. |
| |
| To give a concrete example using protocol buffers, |
| |
| ```java |
| MyProto construct(Stream<Integer> ints) { |
| return MyProto.newBuilder() |
| .addAllSubMessage( |
| ints.map(i -> SubMessage.newBuilder().setVal(i).build())::iterator) |
| .build(); |
| } |
| ``` |
| |
| With the current implementation of the protocol buffer generated code, this will |
| work, but the following minor change will lead to re-iteration and failure, |
| |
| ```java |
| MyProto construct(Stream<Integer> ints) { |
| MyProto.Builder builder = MyProto.newBuilder(); |
| builder.addSubMessageBuilder().setVal(0); |
| return builder |
| .addAllSubMessage( |
| ints.map(i -> SubMessage.newBuilder().setVal(i).build())::iterator) |
| .build(); // build iterates twice, and throws. |
| } |
| ``` |
| |
| To avoid such pitfalls, the `Stream` can either be terminated with |
| `forEachOrdered` |
| |
| ```java |
| MyProto construct(Stream<Integer> ints) { |
| MyProto.Builder builder = MyProto.newBuilder(); |
| ints.map(i -> SubMessage.newBuilder().setVal(i).build()) |
| .forEachOrdered(builder::addSubMessage); |
| return builder.build(); |
| } |
| ``` |
| |
| or collected (with the caveat that the contents of the `Stream` will now be |
| materialized into memory at once), |
| |
| ```java |
| MyProto construct(Stream<Integer> ints) { |
| return MyProto.newBuilder() |
| .addAllSubMessage( |
| ints.map(i -> SubMessage.newBuilder().setVal(i).build()) |
| .collect(toImmutableList())) |
| .build(); |
| } |
| ``` |
| |
| or suppressed using `@SuppressWarnings("StreamToIterable")`. Only suppress if |
| you're sure the API you're using will only iterate the resulting one-shot |
| `Iterable` once, and can't accept a `Stream` or an `Iterator`. |