Join the chat at https://gitter.im/aNNiMON/Lightweight-Stream-API Maven Central Build Status Coverage Status
Stream API from Java 8 rewritten on iterators for Java 7 and below.
- Functional interfaces (
Supplier,Function,Consumeretc); Stream/IntStream/LongStream/DoubleStream(without parallel processing, but with a variety of additional methods and with custom operators);Optional/OptionalInt/OptionalLong/OptionalDoubleclasses;Exceptionalclass - functional way to deal with exceptions;Objectsfrom Java 7.
Stream.of(/* array | list | set | map | anything based on Iterator/Iterable interface */) .filter(..) .map(..) ... .sorted() .forEach(..); Stream.of(value1, value2, value3)... IntStream.range(0, 10)...
Example project: https://github.com/aNNiMON/Android-Java-8-Stream-Example
Unlike Java 8 streams, Lightweight-Stream-API provides the ability to apply custom operators.
Stream.of(...) .custom(new Reverse<>()) .forEach(...); public final class Reverse<T> implements UnaryOperator<Stream<T>> { @Override public Stream<T> apply(Stream<T> stream) { final Iterator<? extends T> iterator = stream.getIterator(); final ArrayDeque<T> deque = new ArrayDeque<T>(); while (iterator.hasNext()) { deque.addFirst(iterator.next()); } return Stream.of(deque.iterator()); } }
You can find more examples here.
In addition to backported Java 8 Stream operators, the library provides:
-
filterNot- negatedfilteroperator// Java 8 stream.filter(((Predicate<String>) String::isEmpty).negate()) // LSA stream.filterNot(String::isEmpty)
-
select- filters instances of the given class// Java 8 stream.filter(Integer.class::isInstance) // LSA stream.select(Integer.class)
-
withoutNulls- filters only not null elementsStream.of("a", null, "c", "d", null) .withoutNulls() // [a, c, d]
-
sortBy- sorts by extractor function// Java 8 stream.sorted(Comparator.comparing(Person::getName)) // LSA stream.sortBy(Person::getName)
-
groupBy- groups by extractor function// Java 8 stream.collect(Collectors.groupingBy(Person::getName)).entrySet().stream() // LSA stream.groupBy(Person::getName)
-
chunkBy- partitions sorted stream by classifier functionStream.of("a", "b", "cd", "ef", "gh", "ij", "klmnn") .chunkBy(String::length) // [[a, b], [cd, ef, gh, ij], [klmnn]]
-
sample- emits every n-th elementsStream.rangeClosed(0, 10) .sample(2) // [0, 2, 4, 6, 8, 10]
-
slidingWindow- partitions stream into fixed-sized list and sliding over the elementsStream.rangeClosed(0, 10) .slidingWindow(4, 6) // [[0, 1, 2, 3], [6, 7, 8, 9]]
-
takeWhile/dropWhile- introduced in Java 9, limits/skips stream by predicate functionStream.of("a", "b", "cd", "ef", "g") .takeWhile(s -> s.length() == 1) // [a, b] Stream.of("a", "b", "cd", "ef", "g") .dropWhile(s -> s.length() == 1) // [cd, ef, g]
-
scan- iteratively applies accumulation function and returns StreamIntStream.range(1, 6) .scan((a, b) -> a + b) // [1, 3, 6, 10, 15]
-
indexed- adds an index to every element, result isIntPairStream.of("a", "b", "c") .indexed() // [(0 : "a"), (1 : "b"), (2 : "c")]
-
filterIndexed/mapIndexed/takeWhileIndexed/takeUntilIndexed/dropWhileIndexed/reduceIndexed/forEachIndexed- indexed specialization of operatorsStream.of("a", "b", "c") .mapIndexed((i, s) -> s + Integer.toString(i)) // [a0, b1, c2]
No more ugly try/catch in lambda expressions.
// Java 8 stream.map(file -> { try { return new FileInputStream(file); } catch (IOException ioe) { return null; } }) // LSA stream.map(Function.Util.safe(FileInputStream::new))
Download latest release or grab via Maven:
<dependency> <groupId>com.annimon</groupId> <artifactId>stream</artifactId> <version>1.1.7</version> </dependency>
or Gradle:
dependencies {
...
compile 'com.annimon:stream:1.1.7'
...
}Also included version for Java ME. Checkout javame branch.
For use lambda expressions in Java 6, Java 7 or Android, take a look at Retrolambda repository.