Skip to content

aNNiMON/Lightweight-Stream-API

Folders and files

NameName
Last commit message
Last commit date

Latest commit

7aa43e8 · Feb 20, 2024
Feb 20, 2024
Mar 20, 2021
May 19, 2021
May 19, 2021
Aug 14, 2017
Oct 21, 2020
Mar 20, 2021
Aug 2, 2022
Apr 3, 2021
Apr 3, 2021
Dec 8, 2016
Apr 3, 2021
Apr 17, 2018
Mar 20, 2021

Repository files navigation

Lightweight-Stream-API

Coverage Status SonarCloud Status SonarCloud Quality Gate
Build Status Maven Central javadoc

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 - negated filter 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 elements

    Stream.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 function

    Stream.of("a", "b", "cd", "ef", "gh", "ij", "klmnn")
        .chunkBy(String::length) // [[a, b], [cd, ef, gh, ij], [klmnn]]
  • sample - emits every n-th elements

    Stream.rangeClosed(0, 10)
        .sample(2) // [0, 2, 4, 6, 8, 10]
  • slidingWindow - partitions stream into fixed-sized list and sliding over the elements

    Stream.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 function

    Stream.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 Stream

    IntStream.range(1, 6)
        .scan((a, b) -> a + b) // [1, 3, 6, 10, 15]
  • indexed - adds an index to every element, result is IntPair

    Stream.of("a", "b", "c")
        .indexed() // [(0 : "a"), (1 : "b"), (2 : "c")]
  • filterIndexed / mapIndexed / takeWhileIndexed / takeUntilIndexed / dropWhileIndexed / reduceIndexed / forEachIndexed - indexed specialization of operators

    Stream.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.