ScalaFlavor4J provides you Scala flavored useful API in Java.
ScalaFlavor4J is available on the maven central repository. Add the following dependency:
<dependencies>
<dependency>
<groupId>com.m3</groupId>
<artifactId>scalaflavor4j</artifactId>
<version>[1.1,)</version>
</dependency>
</dependencies>
-
_(xxx)
methods are removed because the name is deprecated in Java 8. Please useapply(xxx)
instead. -
FunctionN
are changed from abstract class to interface due to JSR-335 specification. If you want to usecompose
orandThen
, please decorateFunctionN
instances withRichFunctionN
.
In the beginning, please view this presentation. Sorry, We can't put iframe here.
First of all, just import the following package.
import com.m3.scalaflavor4j.*;
import static com.m3.scalaflavor4j.Predef.*; // optional
Provides scala.Function*
.
Scala:
val getLength: Function1[String, Int] = (v: String) => v.length
val getLength: (String) => Int = (v: String) => v.length
val len = getLength("foo")
val len = getLength.apply("foo")
ScalaFlavor4J on Java 8:
F1<String, Integer> getLength = (v) -> v.length();
int len = getLength.apply("foo"); // -> len : 3
VoidFunction* does not exist in Scala.
VoidFunction1<Object> print = (v) -> System.out.println(v);
print.apply("foo"); // "foo"
Provides scala.Option
.
Scala:
val some = Option(3)
some.isDefined
some.orNull(null)
some.getOrElse(0)
some map { i => "found : " + i } getOrElse { "not found" }
some fold ("not found"){ i => "found : " + i }
val none: Option[Int] = Option.empty
none.isDefined
none.getOrElse(0)
none map { i => "found : " + i } getOrElse { "not found" }
none fold ("not found"){ i => "found : " + i }
ScalaFlavor4J on Java 8:
Option<Integer> some = Option.apply(3);
some.isDefined(); // true
some.getOrNull(); // 3
some.getOrElse(0); // 3
some.map(i -> "found : " + i).getOrElse(() -> "not found");
// -> "found : 3"
some.fold("not found").apply(i -> "found : " + i);
// -> "found : 3"
Option<Integer> none = Option.apply(null); // or Option.none();
none.isDefined(); // false
none.getOrNull(); // null
none.getOrElse(0); // 0
none.map(i -> "found : " + i).getOrElse(() -> "not found");
// -> "not found"
none.fold("not found").apply(i -> "found : " + i);
// -> "not found"
Provides scala.collection.Seq
.
Scala:
val words = Seq("foo", "bar", "baz")
ScalaFlavor4J on Java 8:
Using variable arguments:
import java.util.*;
Seq<String> words = Seq.apply("foo", "bar", "baz");
Or apply existing java.util.List
object:
List<String> wordList = Arrays.asList("foo", "bar", "baz");
Seq<String> words = Seq.apply(wordList);
Back to java.util.List
:
List<String> wordList = words.toList();
Scala:
Seq(1, 2, 3, 4, 5) map { (i: Int) => (i * 2).toLong }
Seq(1, 2, 3, 4, 5) flatMap { (i: Int) => 1 to i } mkString(",")
Seq(Some(1), Some(2), None, Some(3), None, Some(4), Some(5)) flatMap { (e: Option[Int]) => e }
ScalaFlavor4J on Java 8:
Seq.apply(1, 2, 3, 4, 5).map(i -> Long.valueOf(i * 2));
// -> Seq.apply(2L, 4L, 6L, 8L, 10L)
Seq.apply(1, 2, 3, 4, 5).flatMap(i -> SInt.apply(1).to(i)).mkString(",");
// -> "1,1,2,1,2,3,1,2,3,4,1,2,3,4,5"
Seq.apply(1, 2, null, 3, null, 4, 5).flatMap(i -> Option.apply(i)).mkString(",");
// -> "1,2,3,4,5"
Scala:
Seq('b', 'c', 'd').foldLeft("a"){ (z: String, c: Char) => z + c }
Seq('b', 'c', 'd').foldRight("a"){ (c: Char, z: String) => z + c }
ScalaFlavor4J on Java 8:
String s = Seq.apply('b', 'c', 'd').foldLeft("a", (z, c) -> z + c);
// -> s : "abcd"
String s = Seq.apply('b', 'c', 'd').foldRight("a", (c, z) -> z + c);
// -> s : "adcb"
Scala:
Seq(1, 2, 3, 4, 5) filter { (i: Int) => i > 2 }
ScalaFlavor4J on Java 8:
Seq.apply(1, 2, 3, 4, 5).filter(i -> i > 2);
// -> Seq.apply(3, 4, 5)
Scala:
Seq(1, 2, 3, 4, 5) foreach { (i: Int) => println(i) }
ScalaFlavor4J on Java 8:
Seq.apply(1, 2, 3, 4, 5).foreach(i -> println(i));
// -> "1" "2" "3" "4" "5"
Provides scala.collection.parallel.ParSeq
. ScalaFlavor4J does not support all the methods that are defined in Scala because some methods are not efficient.
Scala:
(1 to 1000).par.foreach { (i) => print(Thread.currentThread.getId + ",") }
(1 to 1000).par.map { (i) => print(Thread.currentThread.getId + ","); i * i }
(1 to 1000).par.flatMap { (i) => print(Thread.currentThread.getId + ","); 1 to i }
ScalaFlavor4J on Java 8:
SInt.apply(1).to(1000).par().foreach(i -> println(Thread.currentThread.getId() + ","));
SInt.apply(1).to(1000).par().map(i -> {
println(Thread.currentThread.getId() + ",");
return i * i;
});
SInt.apply(1).to(1000).par().flatMap(i -> {
println(Thread.currentThread.getId() + ",");
return SInt.apply(1).to(i);
});
Provides functions that are similar to for-comprehension.
Scala:
val xs1 = Seq("abc", "abcd", "abcde")
val xs2 = Seq(3, 4, 5)
val bs = for (a <- xs1; b <- xs2) yield a.length == b
ScalaFlavor4J on Java 8:
Seq<String> xs1 = Seq.apply("abc", "abcd", "abcde");
Seq<Integer> xs2 = Seq.apply(3, 4, 5);
Seq<Boolean> bs = For.apply(xs1, xs2).yield(tpl -> tpl._1().length() == tpl._2());
// true, false, false, false, true, false, false, false, true
Provides scala.collection.Map
.
Scala:
val sMap = Map("Andy" -> 21, "Brian" -> 18, "Charley" -> 27)
ScalaFlavor4J on Java 8:
Apply an existing java.util.Map
object:
import java.util.*;
Map<String, Integer> ageList = new HashMap<String, Integer>();
ageList.put("Andy", 21);
ageList.put("Brian", 18);
ageList.put("Charley", 27);
SMap<String, Integer> sMap = SMap.apply(ageList);
Back to java.util.Map
:
Map<String, Integer> javaMap = sMap.toMap();
Scala:
val age: Int = sMap.getOrElse("Denis", -1)
ScalaFlavor4J on Java 8:
int age = sMap.getOrElse("Denis", -1);
// -> age : -1
Scala:
sMap foreach { case (k, v) => println(k) }
val withoutCharley = sMap filter { case (k, v) => k.contains("n") }
ScalaFlavor4J on Java 8:
sMap.foreach(v1 -> println(v1._1()));
// -> "Andy" "Brian" "Charley"
SMap<String, Integer> withoutCharley = sMap.filter(v1 -> v1._1().contains("n"));
// -> withoutCharley : ("Andy" -> 21, "Brian" -> 18)
SMap<String, Integer> newMap = sMap.updated("Denis", 24);
// -> newMap : ("Andy" -> 21, "Brian" -> 18, "Charley" -> 27, "Denis" -> 24)
SMap<String, Integer> newMap = sMap.plus(Pair.apply("Denis", 24), Pair.apply("Elle", 19));
// -> newMap : ("Andy" -> 21, "Brian" -> 18, "Charley" -> 27, "Denis" -> 24, "Elle" -> 19)
SMap<String, Integer> newMap = sMap.minus("Charley", "Andy");
// -> newMap : ("Brian" -> 18)
Scala:
val oneToFile: Seq[Int] = 1 to 5
val oneUntilFive: Seq[Int] = 1 until 5
Java:
Seq<Integer> oneToFive = SInt.apply(1).to(5);
// -> oneToFive : Seq.apply(1, 2, 3, 4, 5)
Seq<Integer> oneUntilFive = SInt.apply(1).until(5);
// oneUntilFive : Seq.apply(1, 2, 3, 4)
Provides scala.concurrent.ops._
Scala:
import scala.concurrent.ops._
spawn { println("on a different thread!") }
ScalaFlavor4J on Java 8:
import static com.m3.scalaflavor4j.ConcurrentOps.*;
spawn(() -> println("on a different thread!"));
Scala:
val f = future { Thread.sleep(1000L); "foo" }
ScalaFlavor4J on Java 8:
java.util.concurrent.Future<String> f = future(() -> {
Thread.sleep(1000L);
return "foo";
});
f.get(); // -> "foo"
Provides scala.util.control.Exception._
.
Scala:
import scala.util.control.Exception._
val result: String =
catching(classOf[RuntimeException]) withApply {
(t) => "catched"
} apply {
throw new RuntimeException
}
ScalaFlavor4J on Java 8:
import static com.m3.scalaflavor4j.ExceptionControl.*;
String result = catching(RuntimeException.class)
.withApply(t -> "catched")
.apply(() -> {
// return "ok"; -> result : "ok"
// throw new IOException(); -> will be thrown
throw new RuntimeException();
});
Inspired by "Scala Automatic Resource Management"(Scala Incubator project), but not implemeneted exactly.
import static com.m3.scalaflavor4j.arm.Resource.*;
String content = managed(new FileInputStream("input.txt")).map(is -> "content");
// finally FileInputStream will be closed
Provides scala.io.Source
.
BufferedSource source = Source.fromFile("input.txt", "UTF-8");
BufferedSource source = Source.fromURL("http://docs.scala-lang.org/cheatsheets/", "UTF-8");
Seq<Byte> bs = source.toByteSeq():
Seq<Character> cs = source.toCharSeq():
Seq<String> lines = source.getLines();
You can read more details abouts ScalaFlavor4J in Cookbook.
Copyright 2012 M3, Inc.
Apache License, Version 2.0