Comparison with Streams and Lambdas in JDK8 - GlenKPeterson/Paguro GitHub Wiki
-
When you process data with a Java8+ stream, you have to add
.stream()
. You're no longer forced to end up with a mutable collection, but even if you choose.stream().collect(Collectors.toUnmodifiableList())
it still implements plain oldList
so there are no IDE hints or compiler warnings if you try to call mutator methods like.add(x)
. Paguro's.toImList()
is not just briefer, it also returns anImList
with the mutator methods deprecated. -
There are dead-ends to Java's stream evaluation. For instance Java's
Optional<T>.ifPresent()
andifPresentOrElse()
methods return void. Paguro'sOption<T>
returns a value so you can keep evaluating as long as you like:x = myOption.match(it -> it.doOrReturnSomething() () -> /* do or return something else */)
Plus you can throw checked exceptions from Paguro's lambdas without any fuss (see below).
-
If you later add or remove a few items, Java's Unmodifiable collections require an expensive defensive copy of the entire collection. The Clojure-derived collections in Paguro only duplicate the tiny area of the collection that was changed. As immutable collections go, they have excellent performance.
-
The java.util.function interfaces do nothing to help you with Exceptions. Paguro wraps checked exceptions in unchecked ones for you, so that you can write anonymous functions without worrying about exceptions (as you would in Kotlin, Scala, or Clojure).
-
For up to 2-argument functions, java.util.function has 43 different interfaces. The functional methods on these interfaces are named differently, with a total of 11 different names for
apply()
. Paguro has 3 equivalent interfaces, named by number of arguments (like Scala). All have anapplyEx()
that you override and anapply()
method that callers can use if they want to ignore checked exceptions (they do). If you don't want to return a result, declare the return type as?
and returnnull
. For example:Fn1<Integer,?>
takes an Integer and the return value is ignored. -
I had an enum,
MyEnum
and wanted to passMyEnum::values
as a function reference to a Java 8 stream. The return-type ofMyEnum.values()
isEnum<MyEnum>[]
. An array of a parameterized type. Between theArrays.asList()
, the cast fromMyEnum[]
toEnum<MyEnum>[]
, the checked exception in the method body - what a nightmare! In Paguro, all you need isxformArray(MyEnum.values())
and you're in a happy functional world. -
If you want to define data in Java 8, you end up learning the difference between
Arrays.asList()
andCollections.singletonList()
, or defining one-off classes for every kind of data you might need before you start writing any code. Paguro has a tiny data-definition language (like a type-safe JSON) with extensible Tuples to give your immutable data structures meaningful type-safe names with a minimum of code (see: Usage Example). With Paguro, you can define your data first (using tuples) and name it later. Even the initial anonymous definition is checked by the type system. -
You can still use non-destructive Java 8 stream methods on immutable (or unmodifiable) collections if you want to. Paguro doesn't affect what you do with java.util mutable collections at all.