More core libraries for Java 8+
Kantan provides commonly needed functionality on top of Java 8+ and Guava. It is available in the Maven Central Repository.
<dependency>
<groupId>org.krayne</groupId>
<artifactId>kantan</artifactId>
<version>0.1.0</version>
</dependency>
So you love immutability and you're a
fan of Guava's immutable collections.
You're annoyed that immutable collections are not in the JDK, and frown any time you have to
call collect()
on a stream...
This is your basic ImmutableList
collector.
import org.krayne.kantan.stream.collector.Collectors2
ImmutableList<Integer> collect = Stream.of(1, 2, 3).collect(Collectors2.immutable().toList());
Use Optional
much? Sometimes
you have a stream of these and you only want the present values (immutably, of course). Instead of doing:
Stream<Optional<String>> stream = getStream();
List<String> list = stream
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
ImmutableList<String> immutableList = ImmutableList.copyOf(list);
you can simply do:
Stream<Optional<String>> stream = getStream();
ImmutableList<String> immutableList = stream.collect(Collectors2.immutable().flatteningOptionals());
Do you constantly find your stream-loving self in possession of java.lang.Iterable
s and
java.util.Iterator
s but just want a java.util.stream.Stream
? Do you go to
Stack Overflow every time
you need to do this? How about some simple conversion functions?
Stream.from(someIteratorOrIterable);
If you need a parallel stream, overloaded methods give you that option.
boolean isParallel = true;
Stream.from(someIteratorOrIterable, isParallel);
Kantan provides a number of CompletableFuture
utility methods.
If you've ever needed a completed, exceptional CompletableFuture
, you've probably done:
CompletableFuture<?> f = new CompletableFuture<>();
f.completeExceptionally(t);
return f;
With Kantan, just return Futures.exceptional(t)
Sometimes you just need a CompletableFuture
that runs at a later time. Maybe you're simulating lag.
Whatever the reason, you can do so easily with Futures.delayed()
.
// print "ok" after 3 seconds
Futures.delayed(3000L).runAsync(() -> System.out.println("ok"));
// a future that completes after 3 seconds with the string result, "ok"
Futures.delayed(3000L).supplyAsync(() -> "ok");
// a future that delays the future returned by getSomeFuture() by 3 seconds
Futures.delayed(3000L).supplyFuture(() -> getSomeFuture());
For more control, you can provide a java.util.concurrent.Executor
to use for the delaying thread, as in:
Futures.delayed(3000L, someExecutor).supplyAsync(() -> "ok");
We often want to retry futures a number of times. Perhaps the network was temporarily down, or a
cache write check/set operation failed. With Futures.retrying()
, we can control simple retry behavior.
// future that will retry the supplied operation up to 3 times.
Futures.retrying()
.withRetryCount(3)
.supplyAsync(() -> operationThatMightFail());
// future that will retry the supplied operation up to 3 times, waiting 3 seconds
// between each attempt.
Futures.retrying()
.withRetryCount(5)
.withDelay(3000L)
.supplyAsync(() -> operationThatMightFail());
// future that will retry the supplied operation up to 3 times, waiting a random
// amount of time (from 3 and 10 seconds) between each attempt.
Futures.retrying()
.withRetryCount(5)
.withDelay(3000L, 10000L)
.supplyAsync(() -> operationThatMightFail());
As with delayed futures, you can also pass in a java.util.concurrent.Executor
to use for the retrying
and delaying thread. The retrying future decorator also provides methods to runAsync()
and
supplyFuture()
.
Sometimes you'll want to time your CompletableFuture
s. Maybe you want to log a warning if some operation
takes too long. Enter Futures.timing()
.
Futures.timing(timeInterval -> LOGGER.log("Operation took {} ms", timeInterval.getDuration().toMillis()))
.runAsync(() -> performSomeOperation());