experimenting with Java8 - embrace streams and functional interfaces
Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/7c8c870c Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/7c8c870c Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/7c8c870c Branch: refs/heads/compress-2.0 Commit: 7c8c870c0d43c79174869a232b429e341a79d2ea Parents: 0a76707 Author: Stefan Bodewig <bode...@apache.org> Authored: Wed Mar 23 16:30:39 2016 +0100 Committer: Stefan Bodewig <bode...@apache.org> Committed: Wed Mar 23 16:30:39 2016 +0100 ---------------------------------------------------------------------- .../commons/compress2/archivers/Archivers.java | 127 +++++-------------- .../compress2/archivers/ArchiversTest.java | 4 +- 2 files changed, 31 insertions(+), 100 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-compress/blob/7c8c870c/src/main/java/org/apache/commons/compress2/archivers/Archivers.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/compress2/archivers/Archivers.java b/src/main/java/org/apache/commons/compress2/archivers/Archivers.java index aa1a882..a9e910e 100644 --- a/src/main/java/org/apache/commons/compress2/archivers/Archivers.java +++ b/src/main/java/org/apache/commons/compress2/archivers/Archivers.java @@ -20,16 +20,19 @@ package org.apache.commons.compress2.archivers; import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.Iterator; -import java.util.LinkedHashMap; +import java.util.Spliterator; +import java.util.Spliterators; import java.util.List; import java.util.Map; -import java.util.NoSuchElementException; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import java.util.Set; import java.util.TreeSet; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; /** * Loads ArchiveFormats defined as "services" from {@code @@ -84,28 +87,28 @@ public class Archivers implements Iterable<ArchiveFormat<? extends ArchiveEntry> * Iterates over all known formats that can write archives. */ public Iterable<ArchiveFormat<? extends ArchiveEntry>> getFormatsWithWriteSupport() { - return filter(WRITE_PREDICATE); + return filter(ArchiveFormat::supportsWriting); } /** * Iterates over all known formats that can write archives to channels. */ - public Iterable<ArchiveFormat<? extends ArchiveEntry>> getFormatsWithWriteSupportForChannels() { - return filter(WRITE_TO_CHANNEL_PREDICATE); + public Iterable<ArchiveFormat<? extends ArchiveEntry>> getFormatsWithWriteSupportForNonSeekableChannels() { + return filter(ArchiveFormat::supportsWritingToNonSeekableChannels); } /** * Iterates over all known formats that can read archives from channels. */ - public Iterable<ArchiveFormat<? extends ArchiveEntry>> getFormatsWithReadSupportForChannels() { - return filter(READ_FROM_CHANNEL_PREDICATE); + public Iterable<ArchiveFormat<? extends ArchiveEntry>> getFormatsWithReadSupportForNonSeekableChannels() { + return filter(ArchiveFormat::supportsReadingFromNonSeekableChannels); } /** * Iterates over all known formats that provide random access input. */ public Iterable<ArchiveFormat<? extends ArchiveEntry>> getFormatsWithRandomAccessInput() { - return filter(RANDOM_ACCESS_PREDICATE); + return filter(ArchiveFormat::supportsRandomAccessInput); } /** @@ -118,60 +121,20 @@ public class Archivers implements Iterable<ArchiveFormat<? extends ArchiveEntry> } private void fillMap() throws ServiceConfigurationError { - Set<ArchiveFormat> ts = new TreeSet<ArchiveFormat>(SORT_FOR_AUTO_DETECTION); + Set<ArchiveFormat<? extends ArchiveEntry>> ts = + new TreeSet<ArchiveFormat<? extends ArchiveEntry>>(Archivers::sortForAutoDetection); ts.addAll(asList(formatLoader)); - Map<String, ArchiveFormat<? extends ArchiveEntry>> a = - new LinkedHashMap<String, ArchiveFormat<? extends ArchiveEntry>>(); - for (ArchiveFormat<? extends ArchiveEntry> f : ts) { - a.put(f.getName(), f); - } - archivers = Collections.unmodifiableMap(a); + archivers = Collections.unmodifiableMap(ts.stream() + .collect(Collectors.toMap(ArchiveFormat::getName, Function.identity()))); } - private interface Predicate<T> { boolean matches(T t); } - - private static final Predicate<ArchiveFormat<? extends ArchiveEntry>> WRITE_PREDICATE = - new Predicate<ArchiveFormat<? extends ArchiveEntry>>() { - public boolean matches(ArchiveFormat<? extends ArchiveEntry> a) { - return a.supportsWriting(); - } - }; - - private static final Predicate<ArchiveFormat<? extends ArchiveEntry>> WRITE_TO_CHANNEL_PREDICATE = - new Predicate<ArchiveFormat<? extends ArchiveEntry>>() { - public boolean matches(ArchiveFormat<? extends ArchiveEntry> a) { - return a.supportsWritingToNonSeekableChannels(); - } - }; - - private static final Predicate<ArchiveFormat<? extends ArchiveEntry>> READ_FROM_CHANNEL_PREDICATE = - new Predicate<ArchiveFormat<? extends ArchiveEntry>>() { - public boolean matches(ArchiveFormat<? extends ArchiveEntry> a) { - return a.supportsReadingFromNonSeekableChannels(); - } - }; - - private static final Predicate<ArchiveFormat<? extends ArchiveEntry>> RANDOM_ACCESS_PREDICATE = - new Predicate<ArchiveFormat<? extends ArchiveEntry>>() { - public boolean matches(ArchiveFormat<? extends ArchiveEntry> a) { - return a.supportsRandomAccessInput(); - } - }; - - private static final Predicate<ArchiveFormat<? extends ArchiveEntry>> AUTO_DETECTION_PREDICATE = - new Predicate<ArchiveFormat<? extends ArchiveEntry>>() { - public boolean matches(ArchiveFormat<? extends ArchiveEntry> a) { - return a.supportsAutoDetection(); - } - }; - private Iterable<ArchiveFormat<? extends ArchiveEntry>> filter(final Predicate<ArchiveFormat<? extends ArchiveEntry>> p) { - return new Iterable<ArchiveFormat<? extends ArchiveEntry>>() { - public Iterator<ArchiveFormat<? extends ArchiveEntry>> iterator() { - return new FilteringIterator(Archivers.this.iterator(), p); - } - }; + return () -> StreamSupport.stream(Spliterators.spliterator(archivers.values(), + Spliterator.NONNULL), + false) + .filter(p) + .iterator(); } private static <T> List<T> asList(Iterable<T> i) { @@ -182,48 +145,16 @@ public class Archivers implements Iterable<ArchiveFormat<? extends ArchiveEntry> return l; } - private Comparator<ArchiveFormat> SORT_FOR_AUTO_DETECTION = new Comparator<ArchiveFormat>() { - public int compare(ArchiveFormat a1, ArchiveFormat a2) { - if (a1.supportsAutoDetection() && a2.supportsAutoDetection()) { - return a1.getNumberOfBytesRequiredForAutodetection() - a2.getNumberOfBytesRequiredForAutodetection(); - } - if (!a1.supportsAutoDetection() && !a2.supportsAutoDetection()) { - return 0; - } - if (a1.supportsAutoDetection()) { - return -1; - } - return 1; - } - }; - - private static class FilteringIterator<T> implements Iterator<T> { - private final Iterator<T> i; - private final Predicate<? super T> filter; - private T lookAhead = null; - private FilteringIterator(Iterator<T> i, Predicate<? super T> filter) { - this.i = i; - this.filter = filter; - } - public void remove() { - i.remove(); + private static int sortForAutoDetection(ArchiveFormat a1, ArchiveFormat a2) { + if (a1.supportsAutoDetection() && a2.supportsAutoDetection()) { + return a1.getNumberOfBytesRequiredForAutodetection() - a2.getNumberOfBytesRequiredForAutodetection(); } - public T next() { - if (lookAhead == null) { - throw new NoSuchElementException(); - } - T next = lookAhead; - lookAhead = null; - return next; + if (!a1.supportsAutoDetection() && !a2.supportsAutoDetection()) { + return 0; } - public boolean hasNext() { - while (lookAhead == null && i.hasNext()) { - T next = i.next(); - if (filter.matches(next)) { - lookAhead = next; - } - } - return lookAhead != null; + if (a1.supportsAutoDetection()) { + return -1; } + return 1; } } http://git-wip-us.apache.org/repos/asf/commons-compress/blob/7c8c870c/src/test/java/org/apache/commons/compress2/archivers/ArchiversTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/compress2/archivers/ArchiversTest.java b/src/test/java/org/apache/commons/compress2/archivers/ArchiversTest.java index a32781e..0846244 100644 --- a/src/test/java/org/apache/commons/compress2/archivers/ArchiversTest.java +++ b/src/test/java/org/apache/commons/compress2/archivers/ArchiversTest.java @@ -46,12 +46,12 @@ public class ArchiversTest { @Test public void shouldFindArArchiveFormatAsChannelWritableFormat() { - shouldFind(ArArchiveFormat.class, new Archivers().getFormatsWithWriteSupportForChannels()); + shouldFind(ArArchiveFormat.class, new Archivers().getFormatsWithWriteSupportForNonSeekableChannels()); } @Test public void shouldFindArArchiveFormatAsChannelReadableFormat() { - shouldFind(ArArchiveFormat.class, new Archivers().getFormatsWithReadSupportForChannels()); + shouldFind(ArArchiveFormat.class, new Archivers().getFormatsWithReadSupportForNonSeekableChannels()); } @Test