Lightweight-Stream-API
Stream API from Java 8 rewritten on iterators for Java 7 and below.
Includes
- Functional interfaces (
Supplier
,Function
,Consumer
etc); Stream
/IntStream
/LongStream
/DoubleStream
(without parallel processing, but with a variety of additional methods and with custom operators);Optional
/OptionalBoolean
/OptionalInt
/OptionalLong
/OptionalDouble
classes;Exceptional
class - functional way to deal with exceptions;Objects
from Java 7.
Usage
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
Key features
Custom operators
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.
Additional operators
In addition to backported Java 8 Stream operators, the library provides:
-
filterNot
- negatedfilter
operator// 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 isIntPair
Stream.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]
Throwable functions
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
Download latest release or grab via Maven:
<dependency>
<groupId>com.annimon</groupId>
<artifactId>stream</artifactId>
<version>1.2.2</version>
</dependency>
or Gradle:
dependencies {
...
implementation 'com.annimon:stream:1.2.2'
...
}
or use latest unrealeased features with JitPack.
Also included version for Java ME. Checkout javame branch.