From bc9a25e042d45ccadbe41421ec3521fefb6b2120 Mon Sep 17 00:00:00 2001 From: tfenne Date: Wed, 27 Apr 2016 10:57:48 -0400 Subject: [PATCH 1/2] Utility methods on CloseableIterator to make life a little easier. --- .../samtools/util/CloseableIterator.java | 21 ++++++++++++- .../samtools/util/CloseableIteratorTest.java | 31 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 src/tests/java/htsjdk/samtools/util/CloseableIteratorTest.java diff --git a/src/java/htsjdk/samtools/util/CloseableIterator.java b/src/java/htsjdk/samtools/util/CloseableIterator.java index 9988364934..eeab9c293e 100755 --- a/src/java/htsjdk/samtools/util/CloseableIterator.java +++ b/src/java/htsjdk/samtools/util/CloseableIterator.java @@ -24,7 +24,13 @@ package htsjdk.samtools.util; import java.io.Closeable; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; /** * This interface is used by iterators that use releasable resources during iteration. @@ -40,6 +46,19 @@ * We do not inherit from java.io.Closeable because IOExceptions are a pain to deal with. */ public interface CloseableIterator extends Iterator, Closeable { + /** Should be implemented to close/release any underlying resources. */ + void close(); - public void close(); + /** Consumes the contents of the iterator and returns it as a List. */ + default List toList() { + final List list = new ArrayList<>(); + while (hasNext()) list.add(next()); + return list; + } + + /** Returns a Stream that will consume from the underlying iterator. */ + default Stream stream() { + final Spliterator s = Spliterators.spliteratorUnknownSize(this, Spliterator.ORDERED); + return StreamSupport.stream(s, false); + } } diff --git a/src/tests/java/htsjdk/samtools/util/CloseableIteratorTest.java b/src/tests/java/htsjdk/samtools/util/CloseableIteratorTest.java new file mode 100644 index 0000000000..b96d1f67ce --- /dev/null +++ b/src/tests/java/htsjdk/samtools/util/CloseableIteratorTest.java @@ -0,0 +1,31 @@ +package htsjdk.samtools.util; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class CloseableIteratorTest { + @Test + public void testToList() { + final List expected = Arrays.asList(1,2,3,4,5); + final PeekableIterator peeky = new PeekableIterator<>(expected.iterator()); + final List actual = peeky.toList(); + + Assert.assertEquals(actual, expected); + Assert.assertEquals(peeky.toList(), new ArrayList<>()); // Should be empty the second time + } + + @Test + public void testToStream() { + final List inputs = Arrays.asList(1,2,3,4,5); + final PeekableIterator peeky = new PeekableIterator<>(inputs.iterator()); + final List expected = inputs.stream().map(i -> i*2).collect(Collectors.toList()); + final List actual = peeky.stream().map(i -> i*2).collect(Collectors.toList()); + + Assert.assertEquals(actual, expected); + } +} From 97aacd4d466756abc943a6bf20dcc3d04fa26d48 Mon Sep 17 00:00:00 2001 From: tfenne Date: Wed, 27 Apr 2016 11:25:30 -0400 Subject: [PATCH 2/2] Addressing review feedback --- src/java/htsjdk/samtools/util/CloseableIterator.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/java/htsjdk/samtools/util/CloseableIterator.java b/src/java/htsjdk/samtools/util/CloseableIterator.java index eeab9c293e..d26443e0c3 100755 --- a/src/java/htsjdk/samtools/util/CloseableIterator.java +++ b/src/java/htsjdk/samtools/util/CloseableIterator.java @@ -42,8 +42,6 @@ * 2) When hasNext() returns false, the iterator implementation should automatically close itself. * The latter makes it somewhat safer for consumers to use the for loop syntax for iteration: * for (Type obj : getCloseableIterator()) { ... } - * - * We do not inherit from java.io.Closeable because IOExceptions are a pain to deal with. */ public interface CloseableIterator extends Iterator, Closeable { /** Should be implemented to close/release any underlying resources. */ @@ -53,12 +51,13 @@ public interface CloseableIterator extends Iterator, Closeable { default List toList() { final List list = new ArrayList<>(); while (hasNext()) list.add(next()); + close(); return list; } /** Returns a Stream that will consume from the underlying iterator. */ default Stream stream() { final Spliterator s = Spliterators.spliteratorUnknownSize(this, Spliterator.ORDERED); - return StreamSupport.stream(s, false); + return StreamSupport.stream(s, false).onClose(this::close); } }