snippetjavaMajor
StreamIterable - create an iterable from a Java 8 Stream
Viewed 0 times
streamstreamiterablecreatejavaiterablefrom
Problem
This seems like an easy thing to mess up, so I'd be grateful if you could think of any edge-cases that I've missed.
where
Tests
```
public class StreamIteratableTest {
@Test
public void empty() {
assertThat(new StreamIterable<>(Stream.empty()), Matchers.emptyIterable());
}
@Test
public void matcher() {
Stream stream = Stream.of("1", "2", "3");
assertThat(new StreamIterable<>(stream), Matchers.contains("1", "2", "3"));
}
@Test
public void torture_empty() {
StreamIterator empty = new StreamIterator<>(Stream.empty());
assertFalse(empty.hasNext());
try {
empty.next();
fail();
} catch (NoSuchElementException expected) {
}
assertFalse(empty.hasNext());
assertFalse(empty.hasNext());
try {
empty.next();
fail();
} catch (NoSuchElementException expected) {
}
try {
empty.next();
f
public class StreamIterable implements Iterable {
private final Stream stream;
public StreamIterable(Stream stream) {
this.stream = stream;
}
@Override
public Iterator iterator() {
return new StreamIterator<>(stream);
}
}where
public class StreamIterator implements Iterator {
private final Spliterator spliterator;
private boolean nextIsKnown = false;
private T next = null;
public StreamIterator(Stream stream) {
this.spliterator = stream.spliterator();
}
@Override
public boolean hasNext() {
if (nextIsKnown)
return true;
return spliterator.tryAdvance(t -> {next = t; nextIsKnown = true;});
}
@Override
public T next() {
if (nextIsKnown) {
return resetAndReturnNext();
}
if (!hasNext())
throw new NoSuchElementException();
return resetAndReturnNext();
}
private T resetAndReturnNext() {
T result = next;
nextIsKnown = false;
next = null;
return result;
}
}Tests
```
public class StreamIteratableTest {
@Test
public void empty() {
assertThat(new StreamIterable<>(Stream.empty()), Matchers.emptyIterable());
}
@Test
public void matcher() {
Stream stream = Stream.of("1", "2", "3");
assertThat(new StreamIterable<>(stream), Matchers.contains("1", "2", "3"));
}
@Test
public void torture_empty() {
StreamIterator empty = new StreamIterator<>(Stream.empty());
assertFalse(empty.hasNext());
try {
empty.next();
fail();
} catch (NoSuchElementException expected) {
}
assertFalse(empty.hasNext());
assertFalse(empty.hasNext());
try {
empty.next();
fail();
} catch (NoSuchElementException expected) {
}
try {
empty.next();
f
Solution
Two things:
-
I think you have missed the native implementation. Are you intentionally re-inventing the wheel? Streams have an iterator() method.
-
Note that streams cannot be reversed, so, while you can create an iterator once, from the stream, you cannot create a second iterator.... In other words, you cannot loop more than once through your iterable.
Consider reworking your class as:
That's it, no additional code needed. You can still only iterate it once, but, you can add the above to an enhanced-for loop:
-
I think you have missed the native implementation. Are you intentionally re-inventing the wheel? Streams have an iterator() method.
-
Note that streams cannot be reversed, so, while you can create an iterator once, from the stream, you cannot create a second iterator.... In other words, you cannot loop more than once through your iterable.
Consider reworking your class as:
public class StreamIterable implements Iterable {
private final Stream stream;
public StreamIterable(Stream stream) {
this.stream = stream;
}
@Override
public Iterator iterator() {
return stream.iterator();
}
}That's it, no additional code needed. You can still only iterate it once, but, you can add the above to an enhanced-for loop:
for (String v : new StreamIterable(Files.lines(...)) {
....
}Code Snippets
public class StreamIterable<T> implements Iterable<T> {
private final Stream<T> stream;
public StreamIterable(Stream<T> stream) {
this.stream = stream;
}
@Override
public Iterator<T> iterator() {
return stream.iterator();
}
}for (String v : new StreamIterable(Files.lines(...)) {
....
}Context
StackExchange Code Review Q#70469, answer score: 29
Revisions (0)
No revisions yet.