Stream utilities for Java 8

Overview

protonpack

Maven Central Build Status

A small collection of Stream utilities for Java 8. Protonpack provides the following:

  • takeWhile and takeUntil
  • skipWhile and skipUntil
  • zip and zipWithIndex
  • unfold
  • MapStream
  • aggregate
  • Streamable<T>
  • unique collector

For full API documentation, see (http://poetix.github.io/protonpack).

Available from Maven Central:

<dependency>
    <groupId>com.codepoetics</groupId>
    <artifactId>protonpack</artifactId>
    <version>1.16</version>
</dependency>

takeWhile

Takes elements from the stream while the supplied condition is met. takeUntil does the same, but with the condition negated.

Stream<Integer> infiniteInts = Stream.iterate(0, i -> i + 1);
Stream<Integer> finiteInts = StreamUtils.takeWhile(infiniteInts, i -> i < 10);

assertThat(finiteInts.collect(Collectors.toList()),
           hasSize(10));

skipWhile

Skips elements from the stream while the supplied condition is met. skipUntil does the same, but with the condition negated.

Stream<Integer> ints = Stream.of(1,2,3,4,5,6,7,8,9,10);
Stream<Integer> skipped = StreamUtils.skipWhile(ints, i -> i < 4);

List<Integer> collected = skipped.collect(Collectors.toList());

assertThat(collected,
           contains(4, 5, 6, 7, 8, 9, 10));

zip

Combines two streams using the supplied combiner function.

Stream<String> streamA = Stream.of("A", "B", "C");
Stream<String> streamB  = Stream.of("Apple", "Banana", "Carrot", "Doughnut");

List<String> zipped = StreamUtils.zip(streamA,
                                      streamB,
                                      (a, b) -> a + " is for " + b)
                                 .collect(Collectors.toList());

assertThat(zipped,
           contains("A is for Apple", "B is for Banana", "C is for Carrot"));

unfold

Generates a (potentially infinite) stream using a generator that can indicate the end of the stream at any time by returning Optional.empty().

Stream<Integer> unfolded = StreamUtils.unfold(1, i ->
    (i < 10)
        ? Optional.of(i + 1)
        : Optional.empty());

assertThat(unfolded.collect(Collectors.toList()),
           contains(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));

stream

Transforms a source type into a stream

stream(Optional<T> optional):

Stream<Item> items = idStream.flatMap(id -> StreamUtils.stream(fetchItem(id));

Streamable

Streamable is to Stream as Iterable is to Iterator. Useful when you will want to stream repeatedly over some source.

unique

A collector that returns the one and only item in a stream, if present, or throws an exception if multiple items are found.

assertThat(Stream.of(1, 2, 3).filter(i -> i > 3).collect(CollectorUtils.unique()),
           equalTo(Optional.empty()));

assertThat(Stream.of(1, 2, 3).filter(i -> i > 2).collect(CollectorUtils.unique()),
           equalTo(Optional.of(3)));

// Throws NonUniqueValueException
Stream.of(1, 2, 3).filter(i -> i > 1).collect(CollectorUtils.unique());

toFutureList

A collector that converts a stream of CompletableFuture<T> into a CompletableFuture<List<T>>, which completes exceptionally if (and as soon as) any of the futures in the list completes exceptionally.

Function<Integer, CompletableFuture<Integer>> processAsynchronously = i -> CompletableFuture.completedFuture(i * 2);
assertThat(
        Stream.of(1, 2, 3).map(processAsynchronously)
                .collect(CompletableFutures.toFutureList())
                .get(),
        contains(2, 4, 6));
Comments
  • A collector which forces eager evaluation of a stream

    A collector which forces eager evaluation of a stream

    I end up needing this quite often when dealing with async stuff. Here's mine:

    private static <T> Collector<T, ?, Stream<T>> force() {
        return Collectors.collectingAndThen(Collectors.toList(), List::stream);
    }
    

    So you can say something like:

    Set<String> rappers = loadRappers();
    Set<String> causesOfDeath = rappers.stream()
        .map(causeOfDeathService::findCauseOfDeathAsync)
        .collect(force())
        .flatMap(swallowingExceptions(Future::get))
        .collect(Collectors.toSet());
    

    The point being that without the force, this pipeline will send one request, then wait for it to come back, then send another, etc, whereas with the force, the portion of the pipeline above the force will run for everything before the portion after.

    opened by tomwhoiscontrary 5
  • Additions to MapStream

    Additions to MapStream

    Things i've run into which i need:

    • mapEntryToLong, eg with (k, v) -> ((long) k.hashCode()) << 32 + v.hashCode(), and potentially the int and double versions, for parity with Stream

    • mappingEntriesToValues, eg with (t, e) -> e + " happened at " + t

    Do those make sense? I will try for a PR if so.

    opened by tomwhoiscontrary 4
  • Join merge methods

    Join merge methods

    I needed this on another project, I thought it could be of interest for you? I could not find (although it did not search that much) stream join implementation that is not using something like a flat map.

    Joining stream that are exposing the sorted characteristic can use a sort merge join algorithm.

    opened by hadrienk 4
  • The Adapter returned by the iterator() of the Spliterators fails with AggregatingSpliterator

    The Adapter returned by the iterator() of the Spliterators fails with AggregatingSpliterator

    When using the iterator function on the resulting stream the StreamUtils.aggregate() method returns, the Iterator adapter fails.

    This happens because the tryAdvance of the AggregatingSpliterator calls the Consumer only when the isSameSlide() method returns. This breaks the contract of the tryAdvance() method that must call action for every calls.

        @Override
        public boolean tryAdvance(Consumer<? super List<I>> action) {
            boolean hadElements = source.tryAdvance(curElem -> {
                    if(!isSameSlide(curElem)) {
                        action.accept(currentSlide);
                        currentSlide = new ArrayList<>();
                    }
                    currentSlide.add(curElem);
                }
            );
            if (!hadElements && !currentSlide.isEmpty()) {
                action.accept(currentSlide);
                currentSlide = new ArrayList<>();
            }
            return hadElements;
        }
    

    The hasNext() method of the adapter for the iterator() function returns true only if the action is called.

        /**
         * Creates an {@code Iterator} from a {@code Spliterator}.
         *
         * <p>Traversal of elements should be accomplished through the iterator.
         * The behaviour of traversal is undefined if the spliterator is operated
         * after the iterator is returned.
         *
         * @param <T> Type of elements
         * @param spliterator The spliterator
         * @return An iterator
         * @throws NullPointerException if the given spliterator is {@code null}
         */
        public static<T> Iterator<T> iterator(Spliterator<? extends T> spliterator) {
            Objects.requireNonNull(spliterator);
            class Adapter implements Iterator<T>, Consumer<T> {
                boolean valueReady = false;
                T nextElement;
    
                @Override
                public void accept(T t) {
                    valueReady = true;
                    nextElement = t;
                }
    
                @Override
                public boolean hasNext() {
                    if (!valueReady)
                        spliterator.tryAdvance(this);
                    return valueReady;
                }
    
                @Override
                public T next() {
                    if (!valueReady && !hasNext())
                        throw new NoSuchElementException();
                    else {
                        valueReady = false;
                        return nextElement;
                    }
                }
            }
    
            return new Adapter();
        }
    
    opened by hadrienk 4
  • Refactoring/Defensive-programming

    Refactoring/Defensive-programming

    • Moved selectors and function to their respective package (see issue #14)
    • Added checks to constructor parameters for the spliterators
    • Make all the spliterator classes final
    opened by alexcrt 4
  • Up-to-date documentation

    Up-to-date documentation

    The javadoc in StreamUtils is pretty good, but the README's documentation is outdated. There should be a way to keep the docs automatically up to date.

    Perhaps the outdated documentation could be removed and a link provided to the javadocs or maybe there is a way to generate README from the javadocs.

    opened by jliuhtonen 4
  • Implementation via Spliterators rather than Iterators

    Implementation via Spliterators rather than Iterators

    Implementation via Spliterators would be faster because 1) spliterator API suits for taking/dropping/zipping better, 2) Iterators are anyway converted to spliterators inside the Streams framework.

    opened by leventov 4
  • Unexpected window when stream is shorter than desired window size

    Unexpected window when stream is shorter than desired window size

    The documentation of windowed says that the last window is guaranteed to be of the desired size (possible data loss). Passing in a stream with less than window size elements however results in a window smaller than the desired size.

    In the example below it would be nice if one doesn't get a window of size 1, but rather no window at all.

    IntStream stream = IntStream.of(1);
    List<Integer> sumOfPairs = StreamUtils.windowed(stream.boxed(), 2)
                    .map(x -> x.get(0) + x.get(1))
                    .collect(Collectors.toList());
    
    opened by magzot 3
  • Missing `takeWhileInclusive`, `takeUntilInclusive`, etc

    Missing `takeWhileInclusive`, `takeUntilInclusive`, etc

    I just came across a situation where I needed an inclusive version of takeWhile. This operator would take elements from a stream until but including the first element that does not match the given predicate.

    It would be great if we could add takeWhileInclusive to the protonpack, along with inclusive versions of other operators like takeUntil, skipWhile, etc.

    opened by mariacamenzuli 3
  • Making the last window available

    Making the last window available

    StreamUtils.windowed(Stream.of(1,2,3), 2, 2)

    • [1,2] only

    It would be good to have an option to make the last window available (to avoid data lost). Something like StreamUtils.windowed(Stream.of(1,2,3), 2, 2, true)

    • [1,2], [3]

    From what I saw this is due to the following block in WindowedSpliterator

            if (next.size() != windowSize) {
                next.clear();
            }
    

    Thanks

    opened by WydD 3
  • Offer a null safe way to get a stream on an object

    Offer a null safe way to get a stream on an object

    I began making my own StreamUtils then found this library. Looking through the StreamUtils I couldn't find the null/Optional.empty way to get a stream.

    Example: http://stackoverflow.com/a/29406604/970308

    Does that already exist or could it be added? I'm happy to send a PR.

    opened by checketts 3
  • added MapStream filterKeys and filterValues

    added MapStream filterKeys and filterValues

    Hi,

    This is a helpful shortcut to filter entries without dealing with the extraction of key or value.

    I know it adds to the maintenance but it is a common pattern I had everywhere.

    Per tests:

    mapStream.filterKeys(predicate).collect();
    ...
    mapStream.filterValues(predicate).collect();
    

    Thanks

    opened by mashimom 0
  • Map an Indexed value to another one, maintaining index

    Map an Indexed value to another one, maintaining index

    Maybe i am using it wrongly, but I guess it should be useful to transform values Indexed<T> => Indexed<U> in a more natural way.

    I have a sequential Stream<T>, I deeply care about the positions of the elements, so the first thing I do with them is zipWIthIndex, so that I can have a Stream<Indexed<T>>. Then, I would like to work with U values. If I want to keep the indexes, I would do something like this:

    // Stream<T> myOriginalStream
    // Function<T, U> mapper
    StreamUtils.zipWithIndex(myOriginalStream)
      .map(indexed -> Indexed.index(indexed.getIndex(), mapper.apply(indexed.getValue())))
    

    which is cumbersome. The same result could be done a little more naturally:

    // Stream<T> myOriginalStream
    // Function<T, U> mapper
    
    // first option
    
    StreamUtils.zipWithIndex(myOriginalStream)
                    .map(Indexed::index)
                    .map(i -> i.mapping(mapper))
                    // do something
                   ;
    
    // second option
    
    StreamUtils.zipWithIndex(myOriginalStream)
                    .map(Indexed::index)
                    .map(Indexed.mapping(mapper))
                    // do something
    

    This could be achieved adding the following methods in Indexed:

    public <U> Indexed<U> map(Function<T, U> mapper) {
        return Indexed.index(index, mapper.apply(value));
    }
    
    // for the second option
    public static <T, U> Function<Indexed<T>, Indexed<U>> mapping(Function<T, U> mapper) {
        return i -> i.map(mapper);
    }
    

    A way to verify that this works fine would be as follow (based on ZipTest.zips_a_stream_with_index):

        @Test public void
        zips_a_stream_with_index_and_map() {
            Stream<String> source = Stream.of("Foo", "Bar", "Baz");
    
            List<Indexed<String>> zipped = StreamUtils.zipWithIndex(source)
                    .map(Indexed.mapping(String::toLowerCase))
                    .collect(Collectors.toList());
    
            assertThat(zipped, contains(
                    Indexed.index(0, "foo"),
                    Indexed.index(1, "bar"),
                    Indexed.index(2, "baz")));
        }
    
    opened by jeffque 0
  • Bump junit from 4.13 to 4.13.1

    Bump junit from 4.13 to 4.13.1

    Bumps junit from 4.13 to 4.13.1.

    Release notes

    Sourced from junit's releases.

    JUnit 4.13.1

    Please refer to the release notes for details.

    Changelog

    Sourced from junit's changelog.

    Summary of changes in version 4.13.1

    Rules

    Security fix: TemporaryFolder now limits access to temporary folders on Java 1.7 or later

    A local information disclosure vulnerability in TemporaryFolder has been fixed. See the published security advisory for details.

    Test Runners

    [Pull request #1669:](junit-team/junit#1669) Make FrameworkField constructor public

    Prior to this change, custom runners could make FrameworkMethod instances, but not FrameworkField instances. This small change allows for both now, because FrameworkField's constructor has been promoted from package-private to public.

    Commits
    • 1b683f4 [maven-release-plugin] prepare release r4.13.1
    • ce6ce3a Draft 4.13.1 release notes
    • c29dd82 Change version to 4.13.1-SNAPSHOT
    • 1d17486 Add a link to assertThrows in exception testing
    • 543905d Use separate line for annotation in Javadoc
    • 510e906 Add sub headlines to class Javadoc
    • 610155b Merge pull request from GHSA-269g-pwp5-87pp
    • b6cfd1e Explicitly wrap float parameter for consistency (#1671)
    • a5d205c Fix GitHub link in FAQ (#1672)
    • 3a5c6b4 Deprecated since jdk9 replacing constructor instance of Double and Float (#1660)
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • StreamUtil.interleaving() giving strange ClassCastException

    StreamUtil.interleaving() giving strange ClassCastException

    Method StreamUtil.interleaving() seems to be broken in v1.14. I keep getting this exception:

    java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
    	at com.codepoetics.protonpack.InterleavingSpliterator.tryAdvance(InterleavingSpliterator.java:48)
    	at java.util.Spliterator.forEachRemaining(Spliterator.java:326)
    	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
    	at com.swheel.core.StreamUtilsTest.interleaving(StreamUtilsTest.java:40)
    
    

    The following unit test reproduces this:

    public class StreamUtilsTest {
    
        String cn11 = "11";
        String cn12 = "12";
        String cn21 = "21";
        String cn22 = "22";
    
        List<String> list1 = Arrays.asList(cn11, cn12);
        List<String> list2 = Arrays.asList(cn21, cn22);
    
        @Test
        public void interleaving() {
            AtomicLong evenOdd = new AtomicLong();
            Function<String[], Integer> alternating = cns -> {
                assert cns.length == 2;
                if (cns[0] == null) return 1;
                if (cns[1] == null) return 0;
                if (evenOdd.getAndIncrement() % 2 == 0) {
                    return 0;
                } else {
                    return 1;
                }
            };
    
            List<String> res =
                StreamUtils.interleave(alternating, Arrays.asList(list1.stream(), list2.stream()))
                        .collect(Collectors.toList());
    
            Assert.assertEquals(Arrays.asList(cn11, cn21, cn12, cn22), res);
        }
    }
    
    

    I get no compile errors for this test, but the strange ClassClast at runtime.

    opened by kash74 6
Owner
Dominic Fox
Dominic Fox
Enhancing Java Stream API

StreamEx 0.7.3 Enhancing Java Stream API. This library defines four classes: StreamEx, IntStreamEx, LongStreamEx, DoubleStreamEx which are fully compa

Tagir Valeev 2k Jan 3, 2023
Backport of Java 8's lambda expressions to Java 7, 6 and 5

Retrolambda: Use Lambdas on Java 7 Just as there was Retroweaver et al. for running Java 5 code with generics on Java 1.4, Retrolambda lets you run Ja

Esko Luontola 3.5k Dec 30, 2022
An advanced, but easy to use, platform for writing functional applications in Java 8.

Getting Cyclops X (10) The latest version is cyclops:10.4.0 Stackoverflow tag cyclops-react Documentation (work in progress for Cyclops X) Integration

AOL 1.3k Dec 29, 2022
Java 8 annotation processor and framework for deriving algebraic data types constructors, pattern-matching, folds, optics and typeclasses.

Derive4J: Java 8 annotation processor for deriving algebraic data types constructors, pattern matching and more! tl;dr Show me how to write, say, the

null 543 Nov 23, 2022
vʌvr (formerly called Javaslang) is a non-commercial, non-profit object-functional library that runs with Java 8+. It aims to reduce the lines of code and increase code quality.

Vavr is an object-functional language extension to Java 8, which aims to reduce the lines of code and increase code quality. It provides persistent co

vavr 5.1k Jan 3, 2023
Functional patterns for Java

λ Functional patterns for Java Table of Contents Background Installation Examples Semigroups Monoids Functors Bifunctors Profunctors Applicatives Mona

null 825 Dec 29, 2022
java port of Underscore.js

underscore-java Requirements Java 1.8 and later or Java 11. Installation Include the following in your pom.xml for Maven: <dependencies> <dependency

Valentyn Kolesnikov 411 Dec 6, 2022
A library that simplifies error handling for Functional Programming in Java

Faux Pas: Error handling in Functional Programming Faux pas noun, /fəʊ pɑː/: blunder; misstep, false step Faux Pas is a library that simplifies error

Zalando SE 114 Dec 5, 2022
RustScript is a functional scripting language with as much relation to Rust as Javascript has to Java.

RustScript RustScript is a scripting language as much relation to Rust as JavaScript has to Java I made this for a school project; it's meant to be im

Mikail Khan 25 Dec 24, 2022
Reactive Streams Utilities - Future standard utilities library for Reactive Streams.

Reactive Streams Utilities This is an exploration of what a utilities library for Reactive Streams in the JDK might look like. Glossary: A short gloss

Lightbend 61 May 27, 2021
"Some" Utilities you can use for your Java projects "freely"! Files are compiled with Java-8 and above, but mostly Java-11.

✨ Java-SomeUtils ?? "Some" Utilities you can use for your Java projects "freely"! *"Freely"* forcing you to include the license into your program. Fil

JumperBot_ 2 Jan 6, 2023
Base classes and utilities for Java Carbyne Stack service clients

Carbyne Stack Java HTTP Client This project provides common functionality for the Java-based HTTP clients for the Carbyne Stack microservices. License

Carbyne Stack 5 Oct 15, 2022
Java utilities to throw checked exceptions in a "sneaky" way.

Sneaky Java Java utilities to throw checked exceptions in a "sneaky" way. If you're tired of checked exceptions in lambdas, then this library is made

Semyon Kirekov 24 Dec 3, 2022
Utilities for handling math and showing numbers in Java.

digital Utilities for handling math and showing numbers in Java. What is it? BitConversion allows converting float and double values to int and long v

Tommy Ettinger 9 Nov 16, 2022
Speedment is a Stream ORM Java Toolkit and Runtime

Java Stream ORM Speedment is an open source Java Stream ORM toolkit and runtime. The toolkit analyzes the metadata of an existing SQL database and aut

Speedment 2k Dec 21, 2022
Enhancing Java Stream API

StreamEx 0.7.3 Enhancing Java Stream API. This library defines four classes: StreamEx, IntStreamEx, LongStreamEx, DoubleStreamEx which are fully compa

Tagir Valeev 2k Jan 3, 2023
null 8 Dec 22, 2022
Netflix, Inc. 809 Dec 28, 2022