A library that contains utility classes and scala adapters and adaptations for google guava.
A fork and new home of the now unmaintained Gilt Foundation Classes (com.gilt.gfc
), now called the GFC Collective, maintained by some of the original authors.
Getting gfc-guava
The latest version is 1.0.0, released on 21/Jan/2020 and cross-built against Scala 2.12.x and 2.13.x.
If you're using SBT, add the following line to your build file:
libraryDependencies += "org.gfccollective" %% "gfc-guava" % "1.0.0"
For Maven and other build tools, you can visit search.maven.org. (This search will also list other available libraries from the GFC Collective.)
Contents and Example Usage
org.gfccollective.guava.GuavaConverters / GuavaConversions:
These contain implicit and explicit functions to convert between
com.google.common.base.Optional
andscala.Option
com.google.common.base.Function
,com.google.common.base.Supplier
,com.google.common.base.Predicate
and the respective scala functions.
val foo: Option[String] = ???
// Explicit conversion Option -> Optional
import org.gfccollective.guava.GuavaConverters._
val bar: Optional[String] = foo.asJava
// Implicit conversion Optional -> Option
import org.gfccollective.guava.GuavaConversions._
val baz: Option[String] = bar
// Have an Guava Function
val guavaFunction: Function[String, Int] = ???
// Explicit conversion Function[String, Int] -> (String => Int)
import org.gfccollective.guava.GuavaConverters._
val scalaFunction: String => Int = guavaFunction.asScala
// Implicit conversion (String => Int) -> Function[String, Int]
val guavaFunction2: Function[String, Int] = scalaFunction
// Have an Guava Function
val guavaSupplier: Supplier[String] = ???
// Explicit conversion Supplier[String] -> (() => String)
import org.gfccollective.guava.GuavaConverters._
val scalaFunction: () => String = guavaSupplier.asScala
// Implicit conversion (() => String) -> Supplier[String]
val guavaSupplier2: Supplier[String] = scalaFunction _
// Have an Guava Predicate
val guavaPredicate: Predicate[String] = ???
// Explicit conversion Predicate[String] -> (String => Boolean)
import org.gfccollective.guava.GuavaConverters._
val scalaFunction: String => Boolean = guavaPredicate.asScala
// Implicit conversion (String => Boolean) -> Predicate[String]
val guavaPredicate2: Predicate[String] = scalaFunction
org.gfccollective.guava.RangeHelper:
Helper to convert between com.google.common.collect.Range
and Option tuples [lower-bound, upper-bound):
// Empty Range: None
val rangeOpt: Option[Range[Int]] = RangeHelper.build(None, None)
// Less-than Range: Some( [Inf...10) )
val rangeOpt: Option[Range[Int]] = RangeHelper.build(None, Some(10))
// At-least Range: Some( [10...Inf) )
val rangeOpt: Option[Range[Int]] = RangeHelper.build(Some(10), None)
// Closed-open Range: Some( [10...20) )
val rangeOpt: Option[Range[Int]] = RangeHelper.build(Some(10), Some(20))
// Singleton Range: Some( [10] )
val rangeOpt: Option[Range[Int]] = RangeHelper.build(Some(10), Some(10))
org.gfccollective.guava.cache.BulkLoadingCache:
Wrapper for Guava's LoadingCache/CacheBuilder API with a bulk cache load and replacement strategy.
// How often should the cache reload (ms)?
val reloadPeriodMs: Long = ???
// Have a bulk load function that returns a KV-tuple Iterator
def loadAll(): Iterator[(Int, String)] = ???
// Build the cache with defaults
val myCache1 = BulkLoadingCache(reloadPeriodMs,
loadAll)
// Optionally use a customized guava CacheBuilder
// Default uses an instance with default settings, including strong keys, strong values,
// and no automatic eviction of any kind
val cacheBuilder: CacheBuilder[_, _] = ???
// Optionally have a cache-miss function
// Default throws a RuntimeException on cache-miss
def onCacheMiss(key: Int): String = ???
// Optionally specify the cache initialization strategy (sync or async)
// Default is to initialize the cache synchronously
val initStrategy = CacheInitializationStrategy.ASYNC
// Optionally have a ScheduledExecutorService
// Default creates a new scheduled thread pool of size 1
val executor: ScheduledExecutorService = ???
// Build the cache fully customized
val myCache2 = BulkLoadingCache(reloadPeriodMs,
loadAll,
cacheBuilder,
onCacheMiss,
initStrategy,
executor)
org.gfccollective.guava.future.FutureConverters:
Provides conversions between scala Future and guava ListenableFuture/CheckedFuture instances.
// Have a Scala Future
val scalaFuture: Future[String] = ???
// Convert to Guava ListenableFuture
import org.gfccollective.guava.future.FutureConverters._
val listeableFuture: ListenableFuture[String] = scalaFuture.asListenableFuture
// Convert to Guava CheckedFuture:
// Needs an implicit Exception mapper to lift Exception to the checked type:
implicit val em: Exception => SomeException = e: Exception => new SomeException(e)
val checkedFuture: CheckedFuture[String, SomeException] = scalaFuture.asCheckedFuture
// Have a Guava ListenableFuture
val guavaFuture: ListenableFuture[String] = ???
// Convert to Guava ListenableFuture
import org.gfccollective.guava.future.FutureConverters._
val scalaFuture: Future[String] = guavaFuture.asScala
Note that Scala Futures that have been converted to Guava/Java Futures like above do not support cancellation and calling .cancel(mayInterruptIfRunning) will throw an UnsupportedOperationException.
org.gfccollective.guava.future.GuavaFutures
A wrapper for Guava ListenableFuture providing monadic operations and higher-order functions similar to the Scala Future object and class.
- Execute a function asynchronously by wrapping it in a ListenableFuture:
// Have an implicit `java.util.concurrent.ExecutorService`
implicit val es: ExecutorService = ???
// Wrap the asynchronous execution of a function in a ListenableFuture
val future: ListenableFuture[String] = GuavaFutures.future {
"Hello"
}
- Find the first succeeded future from the given collection of futures, discarding the others. Returns None if no future completed successfully.
// Have a collection of ListenableFuture:
val futures: Iterable[ListenableFuture[String]] = ???
// Find the first that succeeds:
val first: ListenableFuture[Option[String]] = GuavaFutures.firstCompletedOf(futures)
- Find the first succeeding future from the given collection of futures, that matches a predicate. Returns None if no future completed successfully.
// Have a collection of ListenableFuture:
val futures: Iterable[ListenableFuture[String]] = ???
// Find the first that succeeds and matches the predicate ("Hello"):
val first: ListenableFuture[Option[String]] = GuavaFutures.firstCompletedOf(futures)(_ == "Hello")
- Monadic functions, similar to
scala.Future
// Have a ListenableFuture
val future: ListenableFuture[String] = ???
import org.gfccollective.guava.future.GuavaFutures._
// Transform using map
val f2: ListenableFuture[Int] = future.map(s => s.length)
// Transform using flatMap
def otherFuture(s: String): Future[Int] = ???
val f3: ListenableFuture[Int] = future.flatMap(otherFuture)
// Filter
val f3: ListenableFuture[String] = future.filter(_.length > 0)
// Foreach
def sideEffect(s:String): Unit = ???
val f4: ListenableFuture[Int] = future.foreach(sideEffect)
- Higher order functions, similar to
scala.Future
// Have a ListenableFuture
val future: ListenableFuture[String] = ???
import org.gfccollective.guava.future.GuavaFutures._
// Handle exceptions that this future might contain
val safeFuture: ListenableFuture[String] = future.recover {
case ex: SomeException => "Failed"
}
// Asynchronously handle exceptions that this future might contain via a new future
def fallback(): ListenableFuture[String] = ???
val safeFuture: ListenableFuture[String] = future.recoverWith {
case ex: SomeException => fallback()
}
// Create a new future by applying the 's' function to the successful result of
// the future, or the 'f' function to the failed result.
def success(s: String): Int = s.length
def failure(t: Throwable): Throwable = new SomeException(t)
val transformedFuture: ListenableFuture[Int] = future.transform(success, failure)
- Alternate "fallback" functions to handle failed futures:
// Have a ListenableFuture
val future: ListenableFuture[String] = ???
import org.gfccollective.guava.future.GuavaFutures._
// Wrap the future value in a Try and instead of failing the future, fail the Try
val safeFuture1: ListenableFuture[Try[String]] = future.withTryFallback
// Wrap the future value in an Option and instead of failing the future, return None
val safeFuture2: ListenableFuture[Option[String]] = future.withOptionFallback()
// Provide a default value, if the future fails:
val safeFuture3: ListenableFuture[String] = future.withDefault("foo")
License
Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0