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.

Overview

Gitpod ready-to-code License GitHub Release Maven Central Build Status Code Coverage Gitter Chat donate patrons

vavr-logo

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 collections, functional abstractions for error handling, concurrent programming, pattern matching and much more.

Vavr fuses the power of object-oriented programming with the elegance and robustness of functional programming. The most interesting part is a feature-rich, persistent collection library that smoothly integrates with Java's standard collections.

Because Vavr does not depend on any libraries (other than the JVM) you can easily add it as standalone .jar to your classpath.

To stay up to date please follow the blog.

Using Vavr

See User Guide and/or Javadoc.

Gradle tasks:

  • Build: ./gradlew check
    • test reports: ./build/reports/tests/test/index.html
    • coverage reports: ./build/reports/jacoco/test/html/index.html
  • Javadoc (linting): ./gradlew javadoc

Contributing

A small number of users have reported problems building Vavr. Read our contribution guide for details.

Comments
  • View as immutable java.util collections without copying

    View as immutable java.util collections without copying

    For efficient interop with general Java code, it would be very handy if the collections could be viewed as immutable java.util collections, without having to populate (eg) a new java.util.HashMap.

    Fixed with #1952:

    • [x] List.asJavaList()

    Addressed in #1933:

    • [ ] Map.asJavaMap()
    • [ ] MultiMap.asJavaMap()
    • [ ] Set.asJavaSet()
    feature «vavr-collection» 
    opened by seanf 43
  • Add Apply between Monad and Functor

    Add Apply between Monad and Functor

    Applicative functors are extremely useful, it would help a lot to have Apply for implementing lenses. Also not sure why Traversable extends Monad ??? Also Monad and Functor are generated to avoid some duplication with the 'Checked' alternative ; but I think it it is probably not worth it ; hacking them (to add default methods for example) is extremely tedious. WDYT?

    feature reverted/closed/duplicate 
    opened by jbgi 43
  • More Stream.in() and Traversable.out() methods

    More Stream.in() and Traversable.out() methods

    Stream<String> Stream.in() // same as Stream.in(System::in, Charset.default()).lines()
    Stream<Byte> Stream.in(InputStream in)
    Stream<Char> Stream.in(InputStream in, Charset charset)
    
    Stream<String> stream.lines() // needs to match current stream component type and convert elements
    
    Traversable.out(OutputStream) // writes bytes
    Traversable.out(OutputStream, Charset) // writes chars
    

    Update: Traversable.toInputStream() and Traversable.toOutputStream() could be also useful.

    feature reverted/closed/duplicate «vavr-collection» 
    opened by danieldietrich 39
  • Added support for navigable fields in SortedMap/TreeMap

    Added support for navigable fields in SortedMap/TreeMap

    1. Added support for navigable fields in SortedMap/TreeMap- Added descendingIterator()/descendingKeySet() methods
    • Added descendingMap() method to create a map with reversed order
    • Added subMap()/headMap()/tailMap() methods to create a subMap view of this map
    • Added floor/ceiling/higher/lower methods to navigate the sorted map
    1. Refactored RedBlackTree to:
    • support ascending/descending sub-trees
    • support descending iterator
    • Changed hierarchy structure:
        RedBlackTree  <----- Node  <--- ValueNode
                       \            \-- Empty
                        \
                         \-- AbstractSubTreeView  <----  AscendingSubTreeView
                                                   \---  DescendingSubTreeView
    
    
    1. Added TreeMapBenchmark
    • Measure TreeMap and new navigable methods performance versus Java/Scala implementation
    • Created BenchmarkPerformanceReporter to show nice looking performance comparison reports.
    feature «vavr-collection» 
    opened by eduardmanas 36
  • Create a Multimap

    Create a Multimap

    We have to make a decision about the type of container that holds values. Scala uses Set but I would use Traversable like in Guava. This allows us to store the same values in containers in certain multimap implementations. On the other side, using the Set as container is much easier to implement and much shorter API

    feature «vavr-collection» 
    opened by danieldietrich 34
  • TreeSet.flatMap - cannot be cast to java.lang.Comparable

    TreeSet.flatMap - cannot be cast to java.lang.Comparable

    Hi,

    I've started to use that great library and just hit an issue when using a TreeSet with a specific comparator, and doing a flatMap on it.

    Here is a test case that reproduces the error:

    public class TreeSetTest {
        @Test
        public void testFlapMap() {
            final TreeSet<Obj> objs = TreeSet.ofAll((o1, o2) -> o1.field.compareTo(o2.field),
                    Stream.of("o1", "o2").map(Obj::new)
            );
            objs.flatMap(o -> List.of(new Obj("nicer " + o.field)));
        }
    
        private static final class Obj {
            private final String field;
    
            private Obj(final String field) {
                this.field = field;
            }
        }
    }
    

    And this will produce the following exception:

    java.lang.ClassCastException: TreeSetTest$Obj cannot be cast to java.lang.Comparable
    
        at javaslang.collection.Comparators.lambda$naturalComparator$7c28a3e$1(Comparators.java:30)
        at javaslang.collection.RedBlackTreeModule$Node.insert(RedBlackTree.java:670)
        at javaslang.collection.RedBlackTree.insert(RedBlackTree.java:103)
        at javaslang.collection.RedBlackTree.ofAll(RedBlackTree.java:90)
        at javaslang.collection.TreeSet.ofAll(TreeSet.java:180)
        at javaslang.collection.TreeSet.flatMap(TreeSet.java:584)
        at javaslang.collection.TreeSet.flatMap(TreeSet.java:589)
        at TreeSetTest.testFlapMap(TreeSetTest.java:24)
    

    Looking at TreeSet.java:589 the actual implementation does:

        @Override
        public <U> TreeSet<U> flatMap(Function<? super T, ? extends Iterable<? extends U>> mapper) {
            return flatMap(naturalComparator(), mapper);
        }
    

    So here it uses a naturalComparator(). Should it maybe use the comparator provided in the TreeSet instance?

    I'm using javaslang 2.0.1 version.

    Thanks for the great work guys, and keep going ;)

    Cheers, /Benoit

    bug !BACK-COMPAT «vavr-collection» help wanted 
    opened by benoitheinrich 31
  • Collection creation behavior changed from 1.2.2 to 2.0.0

    Collection creation behavior changed from 1.2.2 to 2.0.0

    @ggalmazor wrote:

    Currently, IntelliJ can't compile this: public List<String> toList(String... someStrings) {
    List<String> theList = List.of(someStrings);
    return theList;
    }
    But it works if I change the first line on the method to: List<String> theList = List.<String>of(someStrings); 
    
    My intention is to handle the vararg someStrings as a list inside the method, but expose a nice API for consumers of this methods in which they can invoke it like: toList("a", "b", "c", ...)
    
    This is curious because in 1.2.2 it worked flawlessly
    Maybe we could have a List.ofAll(T[] tArray)
    I mean, List.ofAll(T[] tArray) => List<T>
    
    feature 
    opened by danieldietrich 31
  • Multi-Release JAR that contains Java 8 binaries + Java 9 module-info.class

    Multi-Release JAR that contains Java 8 binaries + Java 9 module-info.class

    I need a helping hand regarding our Gradle build for Vavr 1.0.0 (see v1.0.0 branch).

    We have

    • The build uses JDK9
    • We develop in Java 9 (in order to have modules) but we only use Java 8 API

    Additionally we need

    The build.gradle needs to be altered in the way that

    • for each module we get one jar ./vavr-<module>/build/lib/vavr-<module>-<version>.jar
    • the contents of the jar are:
    META-INF
    META-INF/MANIFEST.MF
    META-INF/versions/
    META-INF/versions/9/
    META-INF/versions/9/module-info.class
    io/
    io/vavr/
    io/vavr/<module>/
    io/vavr/<module>/<classes>
    
    • all files are compiled with JDK9 -release 8 compiler arg
    • only module-info.java is compiled with JDK9 -release 9 compiler arg

    Resources

    build/infrastructure/ide reverted/closed/duplicate «non-public» 
    opened by danieldietrich 30
  • Structural Pattern Matching

    Structural Pattern Matching


    Note: I know that this will be a big change, directly before the release of 2.0.0. But Scala-like structural pattern matching for Java will be a real game changer if done right! We need to do this - now. Changing the Match API directly after 2.0.0 is no viable solution.


    List<Tuple3<String, Integer, Double> list = ...;
    
    //
    // x  is of type Tuple3<String, Integer, Double>
    // xs is of type List<Tuple3<String, Integer, Double>>
    //
    list.match()
        .when(List($(), $()))
        .then((x, xs) -> ...);
    
    // Match.of(list) also works
    
    //
    // s is of type String
    //
    list.match()
        .when(List(Tuple3($("begin"), _, _), _))
        .then(s -> ...);
    

    The basic syntax

    • Match.when(pattern).then(function)
    • There will be atomic patterns,
      • named any-value: $(), e.g. when(List($(), $())).then((x, xs) -> ...)
      • named specifc-value: $("test"), e.g. when(List($(1), List.nil())).then(one -> ...)
      • ignoring any-matcher: _, e.g. when(List(_, $())).then(tail -> ...)
    • There will be patterns for types, e.g. List(...), all upper-case
    • There will be matchers like is(...), isIn(...), all lower-case

    Changes to the current Match API:

    • The Match implementation will get simpler. The core will fit on one page + generated duplication for arity 0..8 of pattern return values, all methods literally one-liners.

    • MatchFunction will pass away. Maybe we can replace it by o -> Match.of(o).when(...).then(...) or by Match.of(o).when(...).then(...).toFunction() if a function is needed.

    • Never liked the fact that Match grew to an internal DSL, like whenIs, whenIsIn, whenType, whenThis, whenThat. We see similar things in a wide range of other libs, like when().is(), when().isIn(), ... Instead we will compose the match expression with other functions like this:

      list.match()
          .when(is(val))
          .then(v -> ...);
      
      list.match()
          .when(isIn(val1, val2, val3))
          .then(v -> ...);
      

    Match will gain importance

    • it will move to the first level package javaslang

    • it will be as easy to use as 1-2-3.

      import static javaslang.Match.*; // standard patterns $_, $(), $(val), is(), isIn(), type(), ...
      import static javaslang.Patterns.*; // Javaslang types List(x, xs), Tuple3(_1, _2, _3), ...
      
    • it will be extensible, we will be able to create Patterns for existing final classes (without source)

      // we will ship patterns for JDKs. Maybe this needs to be a module for every jdk version
      import javaslang.JDK8Patterns;
      
      // we provide a compile-time code generator for new custom patterns.
      @Patterns
      interface My {
      
          @Pattern(List.class)
          interface List {
              // to be done
          }
      
          @Pattern(Tuple3.class)
          interface Tuple3 {
              // to be done
          }
      
      }
      
      // code generation result
      public final class MyPatterns {
      
          // -- List patterns
          public static Pattern0 List() 
          public static Pattern1 List(Pattern0, Pattern1)
          public static Pattern1 List(Pattern1, Pattern0)
          public static Pattern2 List(Pattern0, Pattern2)
          public static Pattern2 List(Pattern1, Pattern1)
          public static Pattern2 List(Pattern2, Pattern0)
          // ...
      
          // -- Tuple3 patterns
          // ...
      }
      
    feature «vavr-match» 
    opened by danieldietrich 29
  • A Tuple is a Value

    A Tuple is a Value

    Functional programming is all about values and transformation of values using functions.

    Compared to other types Tuples have still a special role in Javaslang. To reflect my statement above in a consistent way, Tuple has to be a Value in Javaslang.

    This is the current type hierarchy:

    javaslang-2 0 0

    Up to now I emphasized the viewpoint that Tuples are Tuples, not more and not less. Especially no other types should be derived from tuples, i.e. they should not be extended.

    But what is the value of a Tuple? In my opinion, the value of a Tuple is the Tuple itself. This is different to all other Value types of Javaslang, which are always wrappers of values in some way (e.g. Option, List, ...).

    Now the big question: Is there any benefit to see a Tuple as a Value of itself, i.e. a Value of a Tuple?

    One benefit is, that Tuple would inherit all operations on Values.

    Is a Tuple not lightweight enough any more if it inherits from Value?

    
    Value<Tuple1<Integer>> val = Tuple.of(1);
    
    class Tuple1<T> implements Tuple, Value<T> {
        ...
    }
    
    feature 
    opened by danieldietrich 29
  • Why are Checked* classes declared to throw Throwable

    Why are Checked* classes declared to throw Throwable

    All Throwable instances must either be an Exception or an Error. The javadoc for Error states that:

    An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch.

    However, because Vavr lambda classes generally declare to throw Throwable, developers end up writing this sort of thing:

    public void doSomething(CheckedRunnable thing) throws MyException {
      try {
        thing.run();
      } catch (SomeExpectedException e) {
         // recover/log/rethrow/whatever
      } catch (Throwable e) { // have to catch because CheckedRunnable declares to throw
        throw new IllegalStateException("I only expected SomeExpectedException", e);
      }
    }
    

    But we've now ended up with any Error being caught and handled by the application. Obviously this can be fixed by doing something like:

      } catch (Exception e) {
        throw new IllegalStateException("I only expected SomeExpectedException", e);
      } catch (Throwable t) {
        throw (Error) t; // we know this must now be an Error
      }
    

    But as Error doesn't have to (or indeed, based on the javadoc, shouldn't) be caught, we really shouldn't have to be doing this.

    This would be avoided if the Checked* signatures instead were:

    @FunctionalInterface
    public interface CheckedRunnable {
        void run() throws Exception;
    }
    

    And the resulting calling code would be safer.

    Aside: I'd actually prefer that the signatures were something like:

    @FunctionalInterface
    public interface CheckedRunnable<E extends Exception> {
        void run() throws E;
    }
    

    or perhaps, to remind users that a lambda may throw a RuntimeException:

    @FunctionalInterface
    public interface CheckedRunnable<E extends Exception> {
        void run() throws E, RuntimeException;
    }
    
    question 
    opened by mrpotes 28
  • LinkedHash(Map|Set) have weird complexity

    LinkedHash(Map|Set) have weird complexity

    Mostly leaving this as a note. LinkedHashMap and LinkedHashSet are, as implemented in the Java standard library, pretty cool structures. Map entries contain a doubly linked list to next and previous elements, and because of the mutability, the cost of maintaining the list structure is always O(1). Effectively, you have a structure which can be treated as both a list and a set without the downsides in most practical cases.

    In Vavr, these structures are implemented as a pair of a HashMap and a Queue. This pairing is rather uncool, because the complexity of various map operations becomes case-dependent.

    For example (all complexities are listed as complexities on the queue, not on the paired HashMap):

    When doing a put, if the element does not exist, the put is O(1). However, doing a put on an element that exists already is O(n) because the element's node is replaced in the queue (and I think the entire queue is copied at this time).

    Likewise, doing a remove is O(n) because the queue must be rewritten.

    The queue is stored as a head and tail with the tail possibly being reversed on dequeue. However, this is only amortized efficient when the reading operation actually dequeues (e.g. n enqs followed by n deqs will do one queue reversal, but n enqs followed by n iterations through the queue will do n queue reversals).

    // This function is O(n^2) though the user will expect it to be O(nlogn + n), since calling head will reverse the entire queue.
    int doSomethingExpensive(int n) {
        LinkedHashSet<Integer> myInts = LinkedHashSet.range(0, 100_000);
        int sum = 0;
        for (int i = 0; i < 100_000; i++) {
            // the head call is presently implemented as .iterator().next() which will prepare the second element for reading, and
            // thus read the entire queue. This could be improved, but the issue remains that reading prefixes of an unchanging map can be expected linear in the entire size of the map.
            sum += doSomethingCheapWith(myInts.head());
    }
    

    In practice this means that the datastructure is genuinely much less effective than the normal HashMap - one converting their HashMap into a LinkedHashMap should expect a huge performance degradation which is unexpected to one coming from normal Java maps.

    An implementation with perhaps slightly poorer top-end performance but that would have much more forgiving worst case performance might be to do something more like:

    - state of LinkedHashMap is (HashMap<K, Tuple2<V, Long>> map, TreeMap<Long, Tuple2<K, V>> indexes, Long nextIndex).
    - Inserting a new element returns (map.put(key, tuple(value, nextIndex)), indexes.put(nextIndex, tuple(key, value)), nextIndex++)
    - overwriting returns (map.put(key, tuple(value, map.get(key)._2), indexes.put(map.get(key)._2, tuple(key, value), nextIndex);
    - remove returns (map.remove(key), indexes.remove(map.get(key)._2), nextIndex)
    - iteration is indexes.values().
    

    This structure would be O(logn) on all operations, and generally avoid the sharp edges of the current structure. It would use quite a bit more memory, although this could be minimized by e.g. avoiding boxing of longs or at least sharing them. Of course, it's possible that top-end performance would suffer, especially since inserting in sorted order is the worst case for a red-black tree.

    opened by j-baker 0
  • Propose Try.toEither(Throwable => L)

    Propose Try.toEither(Throwable => L)

    Thank You

    Thank you for all of the work on Vavr! It has quickly become my favorite Java library, and usually the first thing I add to every new project ❤️ Aside from the benefit to my own code, it has also been a great tool to help teach others about FP and get them curious about it.

    Proposal / What is this?

    I come across cases where I want to convert a Try to an Either while mapping the Failure value onto a Left value. One example would be safely handling code which isn't mine, then mapping the Throwable onto an error type.

    I do this normally either with fold(throwableMapper, identity()) or .toEither().mapLeft(throwableMapper), but find that .toEither(throwableMapper) would be a nice shortcut to replace either case. I have also a few colleagues who would appreciate the addition from a readability standpoint I think, so I thought I'd suggest it.

    Implementation

    By my own style, I'd normally just write this as a wrapper around a fold call. However, as a first contribution, I am trying to stick as close as possible to the style I already see in the code here.

    By that reasoning, the code style, namings, and Javadoc are all created based on examples I find existing within the file.

    Since the toEither(Supplier) implementation assumes the Supplier is pure/will not throw an exception and does not handle such a case, I have followed the same assumption here as well.

    opened by eslep 0
  • Peek() or tap() for tuples

    Peek() or tap() for tuples

    Tuples are missing a method that would return nothing, void. The method signature would be void tap(Closure /*will all tuple elements as input arg*/).

    The use case is when you need to e.g. just to log elements, send something to backend, etc. Yes, the side-effects. :-)

    A similar case is reported for collections: https://github.com/vavr-io/vavr/issues/2676

    Can you please consider it so that we don't have to workaround it?

    Workaround

    Tuple.of(a, b).apply((in1, in2) -> {
       // some side-effects
       
      return "ignored"
    })
    
    opened by zatziky 0
  • CheckedConsumerTests pass whether the CheckedConsumer under test behaves correctly or not

    CheckedConsumerTests pass whether the CheckedConsumer under test behaves correctly or not

    Example:

        @Test
        public void shouldApplyThrowingCheckedConsumer() {
            final CheckedConsumer<?> f = t -> { throw new Error(); };
            try {
                f.accept(null);
                fail("should have thrown");
            } catch(Throwable x) {
                // ok
            }
        }
    

    Since AssertionError is-a Throwable, this test would pass, even if f.accept() didn't throw an error. I don't know how many instances of this problem there are throughout the code base.

    On the one hand, it seems impossible to cause this problem in this context; however, the general pattern is a mistake.

    opened by jbrains 0
  • Introduce leftJoin on Seq

    Introduce leftJoin on Seq

    Very similar to the concept of left joining in a relational database, this method allows joining 2 Seq's based on keys that are extracted from each element.

    opened by tnagelkerke 0
  • Seq.groupBy() preserving insertion order: guaranteed or accident of implementation?

    Seq.groupBy() preserving insertion order: guaranteed or accident of implementation?

    I notice that Collections.groupBy() creates a LinkedHashMap, which preserves insertion order when classifying items by their new key. Is this intended to be guaranteed or is it merely an accident of implementation? If it is intended to be guaranteed, then I would like to add those details to the documentation and perhaps check whether any tests are needed to reflect this guarantee.

    Mostly, I would like to assess my risk in assuming that the various groupBy() implementations will preserve insertion order in the future.

    opened by jbrains 2
Releases(v0.10.4)
  • v0.10.4(Jul 14, 2021)

    Info

    This is a maintenance release for the 0.10.x release train. It back ports bug fixes and improvements from the upcoming 1.0.0 release.

    Please find the complete list of changes here.

    The API Docs can be found here

    Committers

    🎉 MANY THANKS TO ALL COMMITTERS! 🎉

    Changes

    • Option<>.collect() not to call PartialFunction collector on arguments where it is not defined (#2580) @sleepytomcat
    • Iterate once to create two iterators in partition (#2577) @mincong-h
    • Wrong parameter name in Either.filterOrElse JavaDoc (#2618) @gualtierotesta
    • Fix Array#update(int, T) complexity (#2648) @anton0xf
    • more robust slideby classifier function handling (#2642) @jwbargsten
    • Vector.of(T element) performance improvement (#2659) @sleepytomcat
    Source code(tar.gz)
    Source code(zip)
  • v0.10.3(May 15, 2020)

    Info

    This is a maintenance release for the 0.10.x release train.

    Please find the complete list of changes here.

    The API Docs can be found here

    Committers

    🎉 MANY THANKS TO ALL COMMITTERS! 🎉

    Changes

    • Bugfix: #2583 Backport: Re-adds the automatic module name
    • Improvement: #2575 Backport "Avoid unnecessary copy in 'ofAll()' methods" to v0.10
    • Documentation: #2587 Bumps the copyright year to 2020
    Source code(tar.gz)
    Source code(zip)
  • v0.10.2(Aug 2, 2019)

    This patch release fixes the bug of overlapping JPMS module names by removing the Automatic-Module-Name attributes from the MANIFEST.MF files.

    The upcoming release v1.0.0 will not have Automatic-Module-Name attributes.

    The next release v2.0.0 will have proper JPMS modules.

    Source code(tar.gz)
    Source code(zip)
  • v0.10.1(Jul 23, 2019)

    Info

    This is a maintenance release for the 0.10.x release train.

    Please find the complete list of changes here.

    The API Docs can be found here

    Committers

    🎉 MANY THANKS TO ALL COMMITTERS! 🎉

    Changes

    • Bugfix: #2430 Future.reduce considers executor
    • Bugfix: #2426 Fixes DistictIterator to not eat null values
    • Bugfix: #2405 Fixes patmat corner case that might produce a ClassCastException
    • Bugfix: #2403 ClassCastException during pattern matching
    • Bugfix: #2399 Fix: CharSeq implements Comparable
    • Improvement: #2400 Improve performance of last() call on TreeMap
    Source code(tar.gz)
    Source code(zip)
  • vavr-1.0.0-alpha-3(Jul 23, 2019)

    Info

    Caution: This is a preview release of the upcoming major release 1.0.0. It is highly under development and the API is subject to change. Please do not use it in production.

    We are still in the process of moving the changes from the original 1.0.0 branch to master.

    Additionally there are stashed changes that did not make it into the minor release 0.10.0, that may make it into the upcoming 1.0.0 release. This is also work in progress.

    The API Docs can be found here (🚧 currently unavailable because https://www.javadoc.io seems to be down)

    Comitters

    🎉 MANY THANKS TO ALL COMMITTERS! 🎉

    Changes

    Please find the complete list of changes here.

    Source code(tar.gz)
    Source code(zip)
  • v0.10.0(Jan 20, 2019)

    Info

    The minor release 0.10.0 focuses on several API improvements.

    Please find the complete list of changes here.

    The API Docs can be found here

    Comitters

    🎉 MANY THANKS TO ALL COMMITTERS (AND THEIR PATIENCE)! 🎉

    Note: A few contributions didn't made it into 0.10.0 because of backward incompatibilities.

    Changes

    Instead of describing all changes in detail, I will provide a list and show some examples. Beside new features there were also several (internal) improvements not shown here.

    Core/API

    for

    • Change (internal): Removed internal interface io.vavr.Lambda which was on top of the (Checked)Function type hierarchy. It was not public.
    • Feature: For-comprehension supports List, Option, Future, Try
    • Feature: Tuple - append(), concat() and hash()
    • Feature: CheckedConsumer, CheckedPredicate and CheckedRunnable enhancements
    • Feature: PartialFunction now implements Function1
    • Feature: Predicates.not()
    • Feature: Value: toJavaArray(IntFunction), toTree(Function, Function)
    • Deprecation (for removal): API.Map(Tuple2)
    • Deprecation (for removal): API.LinkedMap(Tuple2)
    • Deprecation (for removal): API.SortedMap(Tuple2)
    • Deprecation (for removal): API.SortedMap(Comparator, Tuple2)
    • Deprecation (for removal): API.SortedMap(java.util.Map)
    • Deprecation (for removal): Value.toLeft()
    • Deprecation (for removal): Value.toRight()
    • Deprecation (for removal): Value.toValid()
    • Deprecation (for removal): Value.toInvalid()

    Collections

    for-each-with-index

    • Feature: Traversable: forEachWithIndex, reject(Predicate)
    • Feature: Iterator/Stream: fill(int, Object)
    • Feature: Map/Multimap: reject(BiPredicate), rejectKeys(Predicate), rejectValues(Predicate), keysIterator(), valuesIterator()
    • Feature: Map/Seq: asPartialFunction()
    • Feature: Seq.rotateLeft, rotateRight, takeRight, takeRightUntil, takeRightWhile

    Concurrent

    future

    • Change: Future now uses Executor instead of ExecutorService. The executorService() works as before if Future was initialized with an ExecutorService, otherwise it throws. User executor() instead.
    • Change: Future DEFAULT_EXECUTOR: ForkJoinPool.commonPool()
    • Feature: Future.await(long timeout, TimeUnit unit)
    • Feature: Future.isCancelled()
    • Feature (experimental): (Experimental) Future.run(Task), Future.run(Executor, Task)
    • Deprecation (for removal): Seq/Map/Set withDefault, withDefaultValue

    Controls

    try-fold

    • Feature: Either.sequence, Either.sequenceRight
    • Feature: Either.traverse, Either.traverseRight
    • Feature: Either.filterOrElse
    • Feature: Either.toValidation
    • Feature: Option.traverse
    • Feature: Option.fold
    • Feature: Try.traverse
    • Feature: Try.onFailure
    • Feature: Try.fold
    • Feature: Try.toValidation
    • Feature: Validation.fromTry
    • Feature: Validation.traverse
    • Deprecation (for removal): Either.left(), Either.right()
    • Deprecation (for removal): Either.LeftProjection, Either.RightProjection
    Source code(tar.gz)
    Source code(zip)
  • v0.9.3(Jan 7, 2019)

    Info

    The release increases stability and performance.

    Please find the complete list of changes here.

    The API Docs can be found here

    Comitters

    🎉 MANY THANKS TO ALL COMMITTERS THAT MADE THIS RELEASE POSSIBLE 🎉

    Bug fixes

    🚨 LinkedHashMap duplicate entries

    In Vavr 0.9.2, all LinkedHashMap factory methods internally did not store keys and values correctly.

    Example:

    var map = LinkedHashMap(1, "1", 1, "2", 2, "3", 2, "4");
    
    // = 2 (CORRECT)
    map.size();
    
    // = LinkedHashSet(1, 1, 2, 2) (WRONG)
    // = LinkedHashSet(1, 2) (FIXED)
    map.keySet() = LinkedHashSet(1, 1, 2, 2)
    
    // = List("1", "2", "3", "4") (WRONG)
    // = List("2", "4") (FIXED)
    map.values() = List(1, 2, 3, 4)
    

    Details can be found here.

    🚨 TreeSet fell back to natural comparator after removing all elements

    // = TreeSet(2, 1)
    var set1 = TreeSet.ofAll(Comparator.reverseOrder(), List(1, 1, 2, 2));
    
    // = TreeSet() has now natural comparator (WRONG)
    // = TreeSet() keeps reverse order (FIXED)
    var set2 = set1.removeAll();
    
    // = TreeSet(1, 2) (WRONG)
    // = TreeSet(2, 1) (FIXED)
    set2.addAll(List(1, 1, 2, 2));
    

    Details can be found here.

    🚨 Stream flatMap memory consumption

    Stream.flatMap used an inner class for iteration, with the effect of the result stream holding an unnecessary indirect reference to the head of the source stream, resulting in a "temporary" memory leak.

    However, when the reference to the original Stream was garbage-collected, the memory was completely freed.

    Details can be found here.

    Performance improvements

    🏁 Hash code calculation

    Internally, we relied on

    Objects.hash(T... varargs)
    

    for hashCode calculation. A call

    Objects.hash(1, 2, 3)
    

    results in an array creation. In order to prevent that unnecessary instance creation, we added internal methods that preserve our hash semantics.

    🏁 Micro-optimizations of collections

    We did some micro-optimizations to

    • CharSeq.ofAll(Iterable)
    • CharSeq.prependAll(Iterable)
    • Vector.ofAll(Iterable)
    • Vector.appendAll(Iterable)
    • Vector.prependAll(Iterable)

    Low-level details can be found here.

    New API

    🎉 Map additions

    We follow the Semantic Versioning scheme. Although this release is a patch release, there are two new methods:

    I hope, your OSGi infrastructure does not complain about it.

    Jar files

    📦 Separate annotation processor jar

    We separated annotation vavr-match-processor-<version>.jar from vavr-match-<version>.jar.

    If you want to create your own pattern matching patterns, you need to include these two dependencies now instead of only vavr-match.

    Documentation

    📚 Javadoc improvements

    • We clarified that LinkedHashMap.put(K, V) and LinkedHashMap.add(T) have a worst-case linear complexity. This is because equal elements need to be replaced while preserving their position.
    • Several small improvements and fixes

    Other improvements

    • Improved interoperability with the GWT compiler
    • Improved Eclipse integration for Vavr committers
    Source code(tar.gz)
    Source code(zip)
  • v0.9.2(Nov 24, 2017)

    Contributors

    Daniel Dietrich Erlend Hamnaberg Michael Ummels Pap Lőrinc Robert Erdin Valeriy Vyrva

    Changelog

    Works fine on JDK 9

    Vavr 0.9.2 now works fine on JDK 9. The previous release 0.9.1 had an internal dependency that broke the JDK 9 build - we fixed that.

    Note: JDK 9 introduced a type inference bug that may affect Vavr's pattern matching in some cases. Please see JDK-8039214.

    Collections

    • We fixed the implementation of Multimap.last(). We did not override the default Traversable implementation.
    • We fixed a problem with the intersection of ordered collections that are based on RedBlackTree (such as TreeSet).

    Concurrent

    • We fixed Future.traverse(ExecutorService, Iterable, Function). The ExecutorService was not taken into account.

    More fixes...

    • Beside the above, we fixed some javadoc typos.

    Please find the complete list of changes here.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.1(Sep 17, 2017)

    Contributors

    Christian Bongiorno Daniel Dietrich Emmanuel Touzery Julien Debon Nazarii Bardiuk Pascal Schumacher Ruslan Sennov

    Changelog

    Concurrent operations

    • We fixed a bug that prevented onFailure actions to be performed when a Future has been cancelled.
    • There are known problems with Promise that occur under certain circumstances (see details below). Please note that we did not fix this problem in 0.9.1. We currently work on it in #2093.

    The main thread may be blocked forever if we use an operation that blocks on a Future returned by a Promise. We observed this behavior when we used a ForkJoinPool instead of the default CachedThreadPool.

    Example:

    // we choose a work-stealing thread pool
    ExecutorService executor = java.util.concurrent.ForkJoinPool.commonPool();
    Future<Object> someFuture = Future.of(executor, () -> longRunningTask());
    
    // the internal Future of a Promise might deadlock the system if we block on that Future
    Promise<Object> promise = Promise.make(executor);
    someFuture.onComplete(promise::complete);
    
    // the bug only shows up when calling a blocking operation, like get() or isEmpty()
    Object result = promise.future().get();
    

    Numeric operations

    • Removed the Traversable.min(), max() overloads TreeSet.min() and TreeSet.max()
    • Made Traversable.average(), sum() and product() more accurate.

    TreeSet min()/max()

    TreeSet implements SortedSet, which represents distinct elements that are ordered using a specific Comparator. By default, Traversable.min() and max() calculate the minimum resp. maximum element in linear time O(n) using the natural element order. However, we used the TreeSet collection characteristic to calculate the min() / max() in constant time O(1).

    This was wrong for two reasons:

    1. The Traversable API spec states that min() and max() are calculated using the natural element order. This has to be the case because of the Liskov substitution principle, see examples below.
    2. The minimum of any non-empty collection containing double values is Double.NaN if one or more elements are NaN. But the natural Comparator of Double is defined in the way that NaN >= d for every double d.

    Example:

    // = TreeSet(3, 2, 1)
    Set<Integer> ints = TreeSet.of(Comparator.reverseOrder(), 1, 2, 3);
    
    // = 3 (before), = 1 (after)
    ints.min();
    
    // = 1 (before), = 3 (after)
    ints.max();
    
    // = List(1.0, NaN, 3.0)
    List<Integer> doubles = List.of(1.0, Double.NaN, 3.0);
    
    // = 1.0 (before), = NaN (after)
    doubles.min();
    
    // = NaN (both ok, before and after this change)
    doubles.max();
    

    Traversable average(), sum() and product()

    sum() and product() operate on elements of type Number. Now we return a Number according to the input argument or fallback to double.

    sum() and average() now internally use an improved summation compensation algorithm that fixes problems that occur in standard Java.

    Example:

    // = OptionalDouble(0.0) (wrong)
    j.u.s.DoubleStream.of(1.0, 10e100, 2.0, -10e100).average()
    
    // = Some(0.75) (correct)
    List.of(1.0, 10e100, 2.0, -10e100).average()
    

    Missing methods

    We added

    • Either.sequence(Iterable<? extends Either<? extends L, ? extends R>>)
    • Either.sequenceRight(Iterable<? extends Either<? extends L, ? extends R>>)

    Examples:

    // = Right(List(all, right)) of type Either<Seq<Integer>, Seq<String>> 
    Either.sequence(List.of(Either.right("all"), Either.right("right")));
    
    // = Left(List(1, 2)) of type Either<Seq<Integer>, Seq<String>> 
    Either.sequence(List.of(Either.left(1), Either.left(2), Either.right("ok")));
    
    // = Right(List(all, right)) of type Either<Integer, Seq<String>> 
    Either.sequenceRight(List.of(Either.right("all"), Either.right("right")));
    
    // = Left(1) of type Either<Integer, Seq<String>> 
    Either.sequenceRight(List.of(Either.left(1), Either.left(2), Either.right("ok")));
    

    Type narrowing

    We changed the generic bounds of these method arguments:

    • Function0<R>.narrow(Function0<? extends R>) (before: narrow(Supplier<? extends R>))
    • Function1<T1, R> Function1.narrow(Function1<? super T1, ? extends R>) (before: narrow(Function<? super T1, ? extends R>))
    • Function2<T1, T2, R> Function2.narrow(Function2<? super T1, ? super T2, ? extends R>) (before: narrow(BiFunction<? super T1, ? super T2, ? extends R>))

    Background: Java is not able to do the following type assignment:

    M<? extends T> m = ...;
    M<T> narrowed = m; // does not work but it is correct for immutable objects.
    

    Therefore almost all Vavr types have narrow methods.

    M<? extends T> m = ...;
    M<T> narrowed = M.narrow(m); // works as expected
    

    GWT compatibility fixes

    The following methods were annotated with @GwtIncompatible:

    • Predicates#instanceOf(Class)
    • asJava(), asJava(Consumer), asJavaMutable(), asJavaMutable(Consumer) of io.vavr.collection.Seq and all its subtypes, namely IndexedSeq, LinearSeq, Array, CharSeq, List, Queue, Stream and Vector

    Documentation

    We added more examples and improved the readability of the Javadoc:

    javadoc

    Thanks to Stuart Marks, he was so kind to initiate an issue in order to improve the default Javadoc style.

    You find the Vavr 0.9.1 API specification here.

    More fixes...

    • We removed internal memoization of sortBy() in order to fix an issue with lazy collections that have infinite size
    • We optimized collection conversion
    • We fixed the generics of Multimap builders
    • We improved Traversable.reduceLeft
    • We improved Iterator.dropWhile and slideBy

    Please find the complete list of changes here.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.0(May 16, 2017)

    Changes to the Base Package io.vavr

    We removed the interfaces Kind1 and Kind2. They served as bridge for the removed module javaslang-pure, which contained experimental algebraic extensions.

    Values

    • We removed getOption() in favor of toOption() (which has the same semantics)
    • We changed the functional interface argument of getOrElseTry(CheckedFunction0) (was: getOrElseTry(Try.CheckedSupplier))
    • We removed the conversion method toStack()
    • We replaced the conversion methods
      • toJavaList(Supplier) by toJavaList(Function)
      • toJavaSet(Supplier) by toJavaSet(Function)
    • We added introspection methods isAsync() and isLazy() that provide information about a Value type at runtime
    • We added getOrNull() which returns null if the Value is empty
    • We added Java-like collect() methods
    • We added several conversion methods:
      • toCompletableFuture()
      • toEither(Supplier)
      • toEither(L)
      • toInvalid(Supplier)
      • toInvalid(T)
      • toJavaArray(Class)
      • toJavaCollection(Function)
      • toJavaCollection(Supplier)
      • toJavaList(Function)
      • `toJavaMap(Supplier, Function, Function
      • toJavaParallelStream()
      • toJavaSet(Function)
      • toLinkedMap(Function)
      • toLinkedMap(Function, Function)
      • toLinkedSet()
      • toMap(Function, Function)
      • toPriorityQueue()
      • toPriorityQueue(Comparator)
      • toSortedMap(Comparator, Function)
      • toSortedMap(Comparator, Function, Function)
      • toSortedMap(Function)
      • toSortedMap(Function, Function)
      • toSortedSet()
      • toSortedSet(Comparator)
      • toValid(Supplier)
      • toValid(E)
      • toValidation(Supplier)
      • toValidation(L)

    Functions

    We removed the interface λ (the mother of all functions). It was neat but it had no practical purpose. The unicode character caused several problems with 3rd party tools, which did not handle unicode characters properly.

    • We renamed the interface io.vavr.λ to io.vavr.Lambda and removed it from the public API.
    • We removed the interface λ.Memoized from the public API.

    We added PartialFunction, which is an enabler for

    • a more performant pattern matching implementation

    Functional interfaces

    With Vavr 0.9 we bundled our functions in io.vavr.

    • We moved the functional interfaces Try.CheckedConsumer, Try.CheckedPredicate, Try.CheckedRunnable to io.vavr.
    • We replaced the functional interface Try.CheckedSupplier by the existing CheckedFunction0.

    Exception Handling

    We added some methods to

    • uncheck an existing throwing function, e.g.
      CheckedFunction(x -> { throw new Error(); }).unchecked()
    • lift checked functions to an Option return type, e.g.
      // = None
      CheckedFunction1.lift(x -> { throw new Error(); }).apply(o);
    • lift checked functions to a Try return type, e.g.
      // = Failure(Error)
      CheckedFunction1.liftTry(x -> { throw new Error(); }).apply(o);

    Other Factory Methods

    • create constant functions, e.g.
      Function2.constant(1).apply(what, ever); // = 1
    • narrowing the generic types, e.g.
    Function0<? extends CharSequence> f_ = () -> "hi";
    Function0<CharSequence> f = Function0.narrow(f_);
    

    Tuples

    • We renamed transform() to apply(), e.g.
      y = f(x1, x2, x3) can be understood as y = Tuple(x1, x2, x3).apply(f).

    Additions:

    • Tuple fields can be updated using one of the update* methods, e.g.
      Tuple(1, 2, 3).update2(0).
    • A Tuple2 can be swapped, e.g. Tuple(1, 2).swap().
    • Tuples can be created from java.util.Map.Entry instances, e.g.
      Tuple.fromEntry(entry) // = Tuple2
    • Tuples can be sequenced, e.g.
      Tuple.sequence1(Iterable<? extends Tuple1<? extends T1>>) // = Tuple1<Seq<T1>>
    • Tuples can be narrowed, e.g.
      Tuple.narrow(Tuple1<? extends T1>) // = Tuple1<T1>

    The API Gateway

    We added io.vavr.API that gives direct access to most of the Vavr API without additional imports.

    We are now able to start using Vavr by adding one gateway import. More imports can be added on demand by the IDE.

    'Companion' Factory Methods

    import static io.vavr.API.*;
    

    The new static factory methods serve two things:

    1. They add syntactic sugar.

    E.g. instead of Try.of(() -> new Error()) we now just write Try(() -> new Error()).

    1. They reflect the expected return type.
    Try<Integer>     _try    = Try(1);
    Success<Integer> success = Success(1);
    Failure<Integer> failure = Failure(new Error());
    
    Option<Integer> option   = Option(1);
    Some<Integer>   some     = Some(1);
    None<Integer>   none     = None();
    
    Array<Integer>  array    = Array(1, 2, 3);
    List<Integer>   list     = List(1, 2, 3);
    Stream<Integer> stream   = Stream(1, 2, 3);
    Vector<Integer> vector   = Vector(1, 2, 3);
    
    Tuple1<T>       tuple1   = Tuple(t);
    Tuple3<T, U, V> tuple3   = Tuple(t, u, v);
    

    E.g. Some(1) is expected to be Option.Some, not Option. However, type narrowing is possible.

    // types work as expected
    Option<CharSeqeuence> option = Some("");
    
    // `str` might be null
    Option<CharSeqeuence> option = Option(str);
    
    // also possible, it is a Some(null)!
    Option<CharSeqeuence> option = Some(null);
    

    Uncheck Functions

    We are now able to uncheck checked functions:

    Function1<String, User> getUserById = CheckedFunction1.of(id -> throw new IOException()).unchecked();
                                     // = CheckedFunction1.of(User::getById).unchecked();
    

    It is recommended to use the API.unchecked() shortcut instead:

    Function1<String, User> getUserById = unchecked(id -> throw new IOException());
                                     // = unchecked(User::getById);
    

    More Syntacic Sugar

    We are now able to println to console without having to type the System.out boilerplate.

    println("easy");
    

    Rapid prototyping may require to defer implementations. We use TODO() for that purpose:

    void fancyNewAlgorithm(Arg arg) {
        return TODO("some fancy stuff will appear soon");
    }
    
    fancyNewAlgorithm(TODO("need to construct the `arg`"));
    

    The TODO() calls will throw a NotImplementedError at runtime.

    Pattern Matching

    Internally pattern matching now uses the new PartialFunction interface, which gives a performance boost.

    Pattern Names

    We removed the possibility to create pattern matching cases outside of the pattern scope. Now we always use the existing $() methods to lift objects and functions into a pattern context.

    // before
    Case(obj, ...)          // e.g. Case(1, ...)
    Case(predicate, ...)    // e.g. Case(t -> true, ...)
    
    // after
    Case($(obj), ...)       // e.g. Case($(1), ...)
    Case($(predicate), ...) // e.g. Case($(t -> true), ...)
    

    Our pattern generator vavr-match follows the new naming scheme and adds a $ to all generated pattern names.

    Please prefix all patterns with $, e.g. $Some(...) instead of Some(...).

    import static io.vavr.API.*;
    import static io.vavr.Patterns.*;
    
    // same as `intOption.map(i -> i * 2).getOrElse(-1)`
    String result = Match(intOption).of(
        Case($Some($()), i -> i * 2),
        Case($None(), -1)
    );
    

    More details here.

    Pre-defined Patterns

    Accordingly all pattern names in io.vavr.Patterns are now prefixed with a $, and

    • we replaced the List() patterns by $Cons(...) and $Nil().
    • we removed the Stream() patterns because we need to enhance our pattern generator to express inner patterns $Stream.Cons(...) and $Stream.Empty() (API not finished).

    More details here.

    Pre-defined Predicates

    We added the predicates:

    • exists(Predicate)
    • forAll(Predicate)
    • instanceOf(Class)
    • isNotNull()
    • isNull()

    More details here.

    Changes to the Base Package io.vavr.control

    Try keeps original Exception

    • We removed Try.FatalException and Try.NonFatalException
    • Instead we sneaky throw the original exception when calling get() (even if it is checked!)

    For additions see the Try API.

    Changes to the Collections io.vavr.collection

    • We removed AbstractIterator from the public API
    • We changed the index type from long to int. That strikes many methods, like take(int), drop(int), zipWithIndex(), ...
    • We removed the unsafe Map.of(Object...) factory methods which interpreted the given objects as pairs.
    • We added the safe Map.of(K, V, ...) factory methods (up to 10 key/value pairs).

    Java Collection Views

    Our sequential collections, i.e. all collections that implement Seq, can be converted to a java.util collection view in O(1).

    We provide conversion method for mutable and immutable collections. By default collections are immutable, like our persistent collections.

    java.util.List<Integer> list = Vector(1, 2, 3).asJava();
    

    More examples can be found here.

    More Collections

    We completely re-implemented Vector.

    We added more collections:

    • BitSet
    • PriorityQueue
    • Multimap: HashMultimap and LinkedHashMultimap
    • SortedMultimap: TreeMultimap

    The collections got many additions. Please check out the API docs for further details.

    Source code(tar.gz)
    Source code(zip)
  • javaslang-v2.0.6(May 12, 2017)

    Committers

    Daniel Dietrich Gregor Trefs Jan Ferko Pap Lőrinc Przemek Wesołek Ruslan Sennov

    Changelog

    Base

    #1891 Changed generic bounds of Predicates allOf(), anyOf() and noneOf()

    We needed to change the signatures because some Match expressions did not compile.

    -   public static <T> Predicate<T> allOf(Predicate<? super T>... predicates) { ... }
    +   public static <T> Predicate<T> allOf(Predicate<T>... predicates) { ... }
    

    Instead of

    Match(value).of(
            Case(instanceOf(Either.LeftProjection.class), false),
            Case(instanceOf(Either.RightProjection.class), false),
            Case(instanceOf(Future.class), false),
            Case(instanceOf(Iterator.class), false),
            Case(instanceOf(Validation.class), false),
            Case(instanceOf(Either.class), true),
            Case(instanceOf(Option.class), true),
            Case(instanceOf(Try.class), true),
            Case(instanceOf(Traversable.class), true)
    );
    

    we are now able to write

    Match(value).of(
            Case(anyOf(
                    instanceOf(Either.LeftProjection.class),
                    instanceOf(Either.RightProjection.class),
                    instanceOf(Future.class),
                    instanceOf(Iterator.class),
                    instanceOf(Validation.class)
            ), false),
            Case(anyOf(
                    instanceOf(Either.class),
                    instanceOf(Option.class),
                    instanceOf(Try.class),
                    instanceOf(Traversable.class)
            ), true)
    );
    

    The second variant did not compile before.

    #1892 Make interfaces Serializable

    We (unintentionally) changed the interface serializability. E.g. Option wasn't serializable any more (but the classes Some and None are). This hindered us from adding fields of interface types (like Option) to serializable classes.

    Now interfaces extend Serializable. We made an exception for stateful types like Future, Promise and Iterator. These interfaces still to not extend Serializable.

    Collections

    #1796 Fixed stackoverflow problem of List.hashCode().

    The hashCode() calculation for big lists now works as expected.

    List.range(0, 1_000_000)).hashCode();
    

    Note: Additionally we changed the hashCode() of the empty HashArrayMappedTrie, which is the basis for HashMap and HashSet.

    #1792 Fixes deadlock on concurrent class initialization

    We could provoke a deadlock when concurrently using Iterators and the Iterator class wasn't yet initialized by the underlying ClassLoader:

    import javaslang.collection.AbstractIterator;
    import javaslang.collection.Iterator;
    
    /**
     * Created by aeremeev on 25.12.16.
     */
    public class DeadlockTest {
    
        public static void main(String[] args) {
            new Thread(Iterator::empty).start();
            new A();
            System.out.println("Success");
        }
    
        private static class A extends AbstractIterator<Void> {
            @Override
            protected Void getNext() {
                return null;
            }
    
            @Override
            public boolean hasNext() {
                return false;
            }
        }
    }
    

    #1816, #1823 HashArrayMappedTrie.equals() and LeafList.hashCode() fixed

    The following maps should be equal because there is no underlying order.

    final Map<String, Integer> map1 = HashMap.of("Aa", 1, "BB", 2);
    final Map<String, Integer> map2 = HashMap.of("BB", 2, "Aa", 1);
    assertThat(map1).isEqualTo(map2);
    

    Please note that we provoked a hash collision in the example above:

    jshell> "Aa".hashCode()
    $1 ==> 2112
    
    jshell> "BB".hashCode()
    $2 ==> 2112
    

    #1854 LinkedHashMap.keySet() order

    The key set of a LinkedHashMap needs to be a linked set.

    final Set<Integer> keySet = LinkedHashMap.of(4, "d", 1, "a", 2, "b").keySet();
    assertThat(keySet.mkString()).isEqualTo("412");
    

    #1858 Set.add(existing) does nothing, Map.put(existing, any) overwrites

    The Javaslang implementation now acts like this:

    | Set | ovewrites equal elements | | :------- | :------------------------ | | BitSet | no | | HashSet | no | | LinkedHashSet | no | | TreeSet | no |

    | Map | ovewrites (k,v) when
    key equal, value unequal | ovewrites (k,v) when
    key equal, value equal | overwrites old key
    with new key | | :------- | :-------------------------- | :------------------------ | :------------------ | | HashMap | yes | yes | yes | | LinkedHashMap | yes (appends) | yes (appends) | yes | | TreeMap | yes | yes | yes |

    There is one anomaly in Scala: Despite all other Map implementations, HashMap does not update (key, value) when putting a (key, value) that is already present.

    Especially this may bite the user when working with the Map interface and it is not clear which implementations is currently used (see Liskov Substitution Principle).

    In Javaslang, we do consistent updates along all Map implementations.

    #1878 Fixes Traversable.containsAll(Iterable)

    I can't think what came over me.

    default boolean containsAll(Iterable<? extends T> elements) {
    -   final HashSet<T> uniqueElements = HashSet.ofAll(elements);
    -   return toSet().intersect(uniqueElements).size() == uniqueElements.size();
    +   for (T element : elements) {
    +       if (!contains(element)) {
    +           return false;
    +       }
    +   }
    +   return true;
    }
    

    #1907 Fixes memory leak of grouped iterator

    Infinite iterators can be grouped now in constant memory:

    Iterator.continually(1)
            .grouped(100)
            .zipWithIndex()
            .forEach(t -> System.out.println("Group " + t._2));
    

    Functions

    #1837 Changed memoization's computeIfAbsent to synchronized get and put

    We now support function value memoization in recursive calls:

    private static final Function2<Integer, Integer, Integer> recurrent1 = (i1, i2) -> i1 <= 0 ? i1 : Function2Test.recurrent2.apply(i1 - 1, i2) + 1;
    private static final Function2<Integer, Integer, Integer> recurrent2 = Function2Test.recurrent1.memoized();
    
    @Test
    public void shouldCalculatedRecursively() {
        assertThat(recurrent1.apply(11, 11)).isEqualTo(11);
        assertThat(recurrent1.apply(22, 22)).isEqualTo(22);
    }
    

    Property Testing

    #1700 Optimized random value generators

    We now internally use Iterator instead of Stream:

    static <T> Gen<T> of(T seed, Function<? super T, ? extends T> next) {
        Objects.requireNonNull(next, "next is null");
    -   final Iterator<T> iterator = Stream.iterate(seed, next).iterator();
    +   final Iterator<T> iterator = Iterator.iterate(seed, next);
        return ignored -> iterator.next();
    }
    

    Additionally we rewrote

    • frequency(Iterable<Tuple2<Integer, Gen<T>>> generators)
    • intersperse(Gen<T> other)

    Info: This change contains a backward compatible API change:

    interface Gen<T> {
    -   static Gen<Character> choose(char[] characters) {
    +   static Gen<Character> choose(char... characters) {
    }
    

    #1702 ArrayStoreException in Gen.choose(Iterable)

    For instances of generic interfaces, choose was throwing an ArrayStoreException because of different runtime types of the elements within the iterable.

    static <T> Gen<T> choose(Iterable<T> values) {
        ...
    -   final T[] array = stream.toJavaArray((Class<T>) stream.head().getClass());
    +   final T[] array = (T[]) iterator.toJavaArray();
        ...
    }
    

    #1759 Gen.frequency filters non-positive frequencies

    Now Gen.frequency(Iterable) throws an IllegalArgumentException if there are non-positive frequencies (including zero).

    Javadoc

    #1735 Correct prefix-delimiter-suffix in mkString() javadoc

        /**
         ...
    -    * This has the same effect as calling {@code mkString(delimiter, "", "")}.
    +    * This has the same effect as calling {@code mkString("", delimiter, "")}.
         ...
         */
    
    Source code(tar.gz)
    Source code(zip)
  • javaslang-v2.0.5(May 12, 2017)

    Committers

    @ashrko619 @danieldietrich @mduesterhoeft @paplorinc @ruslansennov

    New and Noteworthy

    API Additions

    Javaslang follows the semantic versioning scheme. In the strict sense API additions require a minor version update. However, the additions that are contained in this bugfix release are considered to be fixes, not additional features.

    Beside backward-compatible modifier- and override-fixes, the release includes these API additions:

    • TreeMap/TreeSet.collector() do explicitly enforce that the key/element-type is Comparable. We did this by narrowing a generic parameter. However, the previous version would have lead to a ClassCastException at runtime if the given type were not Comparable.
    interface javaslang.collection.Iterator<T> {
        + static Iterator<BigDecimal> rangeBy(BigDecimal from, BigDecimal toExclusive, BigDecimal step)
    }
    
    class javaslang.collection.TreeMap<K, V> {
        ~ static <K extends Comparable<? super K>, V> Collector<Tuple2<K, V>, ArrayList<Tuple2<K, V>>, TreeMap<K, V>> collector()
        + static <K, V> Collector<Tuple2<K, V>, ArrayList<Tuple2<K, V>>, TreeMap<K, V>> collector(Comparator<? super K> keyComparator)
    }
    
    class javaslang.collection.TreeSet<T> {
        ~ static <T extends Comparable<? super T>> Collector<T, ArrayList<T>, TreeSet<T>> collector()
        + static <T> Collector<T, ArrayList<T>, TreeSet<T>> collector(Comparator<? super T> comparator)
    }
    

    Behavioral Changes

    • Iterator.rangeBy/rangeClosedBy internally now use BigDecimal instead of double to calculate the range (see #1309).
    • Traversable.dropWhile/takeWhile/span behaved incorrect. This is fixed now (see #1641).
    • LinkedHashMap.values() does now preserve insertion order (see #1656).
    • Value.toCharSeq() now returns a string representation of the contained element(s) instead of the container type (see #1685).
    • Traversable.min()/max() throw now NullPointerException in each case if a null element exists (see #1482).

    List of Changes

    Bugfixes

    «base»

    • PR #1691 (fixes #1685) Fixed toCharSeq()
      → 15667be

    «collections»

    • PR #1695 (fixes #1549) Re-worked TreeMap comparators, considering null-keys
      → 2767cf
    • PR #1692 (fixes #1482) min() max() now throw NPE on null values
      → 5326c88, 7c2c906
    • PR #1671 (fixes #1633) use a Vector as accumulator of map.traverse
      → 662cdd7
    • PR #1657 (fixes #1656) Fixes LinkedHashMap::values()
      → 6466e98
    • PR #1646 (fixes #1641) Fixes truncation bug of dropWhile and null handling of takeWhile and dropWhile
      → 6b6d40e
    • PR #1308 (fixes #1309) Iterator range maintenance
      → cc48033
    • PR #1251 (fixes #1249) Map/Set factories with comparator
      → f3f8f99

    Improvements

    «collections»

    • PR #1696 (fixes #1227) Made naturalComparator() a singleton and made use of it
      → 7a9cc48

    Documentation

    «control»

    • PR #1673 (fixes #1670) Updated javadoc of Either.map and .mapLeft
      → f463f29
    • PR #1672 (fixes #1670) javadoc of Either.map + .mapLeft
      → da54383
    Source code(tar.gz)
    Source code(zip)
  • javaslang-v2.0.4(May 12, 2017)

    Committers

    @danieldietrich @jorander @mvh77 @paplorinc @ruslansennov

    New and Noteworthy

    API Additions

    Javaslang follows the semantic versioning scheme. In the strict sense API additions require a minor version update. However, the additions that are contained in this bugfix release are considered to be fixes, not additional features.

    Beside backward-compatible modifier- and override-fixes, the release includes these API additions:

    class javaslang.Lazy<T> {
      + static <T> Lazy<T> narrow(Lazy<? extends T> lazy)
    }
    
    class javaslang.collection.CharSeq {
      + interface CharUnaryOperator {
        char apply(char c)
      }
      + interface CharFunction<R> {
        R apply(char c)
      }
    }
    
    class javaslang.control.Option<T> {
      + static <T> Option<T> when(boolean condition, T value)
    }
    

    Behavioral Changes

    • Option.when(boolean, Supplier) returns Some(null) instead of None if the Supplier returns null.
    • Validation.valid(null) does return Valid(null) instead of throwing a NullPointerException.
    • LinkedHashMap.replace(Tuple2, Tuple2) replaces a pair (if exists) and preserves its position instead of appending it.
    • LinkedHashSet.replace(T, T) replaces an element (if exists) and preserves its position instead of appending it.

    List of Changes

    Bugfixes

    • PR #1269 (fixes #1272) Fixed Option.when in case of a nullable supplier
      → 7e1e7f9, b7be4fc
    • PR #1297 SortedSet.unzip3 overridden
      → 796dfe0, c766726
    • PR #1390 (fixes #1388) Pattern-match generator should use full class names in generated code
      → 84c6f15
    • PR #1400 (fixes #1377) Added a few methods to the public API of collections
      → 3bff648
    • PR #1419 Iterator#iterate should not call supplier function until value is really needed
      → 3d76301, f369a5c
    • PR #1420 Fix TreeMap creation from Java Map
      → 9358416, 8337cc8
    • PR #1512 (fixes #1326) Replaces AbstractMap with Maps.
      → c1f4d98, baf1659
    • PR #1586 (fixes #1585) Taking primitive types into account when converting to Java array.
      → bfb7063
    • PR #1587 NullPointer Exception could occur on equals call.
      → 100cce9
    • PR #1597 Fixes problem with null-keys in LinkedHashMap put() and remove()
      → 7ea1ae4
    • PR #1598 Fixed exception messages in Array
      → 9d5ac62
    • PR #1601 (fixes #1599) Fixes LinkedHashMap/LinkedHashSet replace() methods
      → 7d7712e

    Improvements

    • PR #1242 (fixes #1235) better equals/hashcode impls
      → fbfe9f9, b4c8c56
    • PR #1247 (fixes #1243) LeafSingleton: compare hashCodes before checking equality
      → 9c2fbd2
    • PR #1350 (fixes #1345) Optimized groupBy operations
      → 21c901b, 6d70844, 0a7e912, 0f1bf89
    • PR #1357 makes HAMT iteration 10x faster
      → 49a9aa6, e1235db, 6104935
    • PR #1567 Optimized usage of double-check idiom
      → 9868a9e
    • PR #1571 further improvement of Lazy.get()
      → 3b8171e
    • PR #1577 Lazy access minor speedup
      → 743cb07
    • PR #1588 Allow Validation.valid(null)
      → 5747633
    • PR #1595 Try$NonFatal.of is not intended to be public
      → 6863cff
    • PR #1596 Re-added Traversable.hash in order to stay backward compatible
      → b67699a

    Documentation

    • PR #1538 (fixes #1304) Clarifies Traversable.min()/max() javadoc.
      → 465ca93
    • PR #1541 Unify author tags
      → 9b7797b, ce427b7
    Source code(tar.gz)
    Source code(zip)
  • javaslang-v2.0.3(May 12, 2017)

  • javaslang-v1.2.3(May 12, 2017)

  • javaslang-v2.0.2(May 12, 2017)

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
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
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
Functional programming course

Functional-Programming-101-Java functional programming course with Mohamed Hammad https://www.youtube.com/playlist?list=PLpbZuj8hP-I6F-Zj1Ay8nQ1rMnmF

Ibrahim 14 Nov 9, 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
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
Stream utilities for Java 8

protonpack A small collection of Stream utilities for Java 8. Protonpack provides the following: takeWhile and takeUntil skipWhile and skipUntil zip a

Dominic Fox 464 Nov 8, 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
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
jedibot is an application that aims to do beneficial actions on the Ethereum blockchain for the DeFi ecosystem while earning a profit for the user.

jedibot is an application that aims to do beneficial actions on the Ethereum blockchain for the DeFi ecosystem while earning a profit for the user. These actions include maintaining the DAI peg, providing liquidity and liquidating undercollateralized assets.

我是高天才! 10 Feb 5, 2022
Using this library, and writing a few lines of code, you can manage your own domain objects in ZooKeeper

Using this library, and writing a few lines of code, you can manage your own domain objects in ZooKeeper. It provides CRUD operations and change notifications out of the box.

Sahab 4 Oct 26, 2022
An extremely easy way to perform background processing in Java. Backed by persistent storage. Open and free for commercial use.

The ultimate library to perform background processing on the JVM. Dead simple API. Extensible. Reliable. Distributed and backed by persistent storage.

JobRunr 1.3k Jan 6, 2023
This is an automated library software built in Java Netbeans to reduce manual efforts of the librarian, students to ensure smooth functioning of library by involving RFIDs.

Advanced-Library-Automation-System This is an advanced automated library software built in Java Netbeans to reduce manual efforts of the librarian, st

DEV_FINWIZ 14 Dec 6, 2022
Android library that allows you to determine your location in a few of lines!

locsimple Android library that allows you to determine your location in some lines! Benefits: automatic processing of permissions processing of enabli

Dmitry 7 Aug 31, 2022
simple web3j Demo to be continue,use web3j Brainless Trading,tool for arbitrage automatic trading, copying other transfer,tracking agency addresses, setting profit points, setting prices, grabbing blocks

simple web3j Demo to be continue,use web3j Brainless Trading,tool for arbitrage automatic trading, copying other transfer,tracking agency addresses, setting profit points, setting prices, grabbing blocks

Nate River 262 Jan 7, 2023
✨LiteFlowX is an idea plugin to increase productivity when using the LiteFlow framework.

LiteFlowX English | 简体中文 LiteFlowX is designed to increase productivity when you use the LiteFlow framework. ?? LiteFlowX Features: Support for LiteFl

码农小易 13 Dec 15, 2022