melito00
11/7/2014 - 11:15 AM

Playing with Java 8 Stream from Scala 2.11.5

Playing with Java 8 Stream from Scala 2.11.5

// $ scala-2.11.5 -Xexperimental

// Original Java 8 version: http://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/

scala> import java.util.{Arrays, List, ArrayList}
scala> import java.util.stream.{Stream, IntStream}

// List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1");

scala> val myList = Arrays.asList("a1", "a2", "b1", "c2", "c1")
myList: java.util.List[String] = [a1, a2, b1, c2, c1]

/*
myList
    .stream()
    .filter(s -> s.startsWith("c"))
    .map(String::toUpperCase)
    .sorted()
    .forEach(System.out::println);
*/
scala> myList.stream.filter(s => s.startsWith("c")).map(_.toUpperCase).sorted.forEach(println)
C1
C2

/*
Arrays.asList("a1", "a2", "a3")
    .stream()
    .findFirst()
    .ifPresent(System.out::println);  // a1
*/
scala> Arrays.asList("a1", "a2", "a3").stream.findFirst.ifPresent(println)
a1

/*
Stream.of("a1", "a2", "a3")
    .findFirst()
    .ifPresent(System.out::println);  // a1
*/
scala> Stream.of("a1", "a2", "a3").findFirst.ifPresent(println)
a1

/*
IntStream.range(1, 4)
    .forEach(System.out::println);
*/
scala> IntStream.range(1, 4).forEach(println)
1
2
3

/*
Arrays.stream(new int[] {1, 2, 3})
    .map(n -> 2 * n + 1)
    .average()
    .ifPresent(System.out::println);  // 5.0
*/
scala> Arrays.stream(Array(1, 2, 3)).map(n => 2 * n + 1).average.ifPresent(println)
5.0


/*
Stream.of("a1", "a2", "a3")
    .map(s -> s.substring(1))
    .mapToInt(Integer::parseInt)
    .max()
    .ifPresent(System.out::println);  // 3
*/
// need explicit type arg
scala> Stream.of("a1", "a2", "a3").map(_.substring(1)).mapToInt(Integer.parseInt).max.ifPresent(println)
3

/*
IntStream.range(1, 4)
    .mapToObj(i -> "a" + i)
    .forEach(System.out::println);
*/
scala> IntStream.range(1, 4).mapToObj(i => "a" + i).forEach(println)
a1
a2
a3


/*
Stream.of(1.0, 2.0, 3.0)
    .mapToInt(Double::intValue)
    .mapToObj(i -> "a" + i)
    .forEach(System.out::println);
*/
scala> Stream.of(1.0, 2.0, 3.0).mapToInt(_.intValue).mapToObj(i => "a" + i).forEach(println)
a1
a2
a3

/*
Stream.of("d2", "a2", "b1", "b3", "c")
    .filter(s -> {
        System.out.println("filter: " + s);
        return true;
    });
*/
scala> Stream.of("d2", "a2", "b1", "b3", "c").filter{ s => println(s"filter: $s"); true }
res9: java.util.stream.Stream[String] = java.util.stream.ReferencePipeline$2@4648ce9

scala> .forEach{s => println(s"forEach: $s")}
filter: d2
forEach: d2
filter: a2
forEach: a2
filter: b1
forEach: b1
filter: b3
forEach: b3
filter: c
forEach: c

/*
Stream.of("d2", "a2", "b1", "b3", "c")
    .map(s -> {
        System.out.println("map: " + s);
        return s.toUpperCase();
    })
    .anyMatch(s -> {
        System.out.println("anyMatch: " + s);
        return s.startsWith("A");
    });
*/
// TODO: type annot
scala> Stream of ("d2", "a2", "b1", "b3", "c") map[String] { s =>
     |       println(s"map: $s")
     |       s.toUpperCase
     |     } anyMatch { s =>
     |       println(s"anyMatch: $s")
     |       s.startsWith("A")
     |     }

/*
Stream.of("d2", "a2", "b1", "b3", "c")
    .filter(s -> {
        System.out.println("filter: " + s);
        return s.startsWith("a");
    })
    .sorted((s1, s2) -> {
        System.out.printf("sort: %s; %s\n", s1, s2);
        return s1.compareTo(s2);
    })
    .map(s -> {
        System.out.println("map: " + s);
        return s.toUpperCase();
    })
    .forEach(s -> System.out.println("forEach: " + s));
*/
scala> Stream of ("d2", "a2", "b1", "b3", "c") filter { s =>
     |         println("filter: " + s)
     |         s.startsWith("a")
     |     } sorted { (s1, s2) =>
     |         println(f"sort: $s1%s; $s2%s\n")
     |         s1.compareTo(s2)
     |     } map { s =>
     |         println("map: " + s)
     |         s.toUpperCase
     |     } forEach { s =>
     |         println("forEach: " + s)
     |     }
filter: d2
filter: a2
filter: b1
filter: b3
filter: c
map: a2
forEach: A2

/**
class Foo {
    String name;
    List<Bar> bars = new ArrayList<>();

    Foo(String name) {
        this.name = name;
    }
}

class Bar {
    String name;

    Bar(String name) {
        this.name = name;
    }
}
*/
scala> case class Bar(name: String)
defined class Bar

scala> class Foo(val name: String, val bars: List[Bar] = new ArrayList())
defined class Foo


/*
List<Foo> foos = new ArrayList<>();

// create foos
IntStream
    .range(1, 4)
    .forEach(i -> foos.add(new Foo("Foo" + i)));

// create bars
foos.forEach(f ->
    IntStream
        .range(1, 4)
        .forEach(i -> f.bars.add(new Bar("Bar" + i + " <- " + f.name))));
*/


scala> val foos = new ArrayList[Foo]()
foos: java.util.ArrayList[Foo] = []


// create foos
scala> IntStream.range(1, 4).forEach(i => foos.add(new Foo("Foo" + i)))


// create bars
scala> foos forEach (f => 
     |   IntStream.range(1, 4) forEach (i => 
     |     f.bars.add(Bar(s"Bar$i <- ${f.name}")))
     |   )

/*
foos.stream()
      .flatMap(f -> f.bars.stream())
      .forEach(b -> System.out.println(b.name));
*/
scala> foos.stream flatMap (_.bars.stream) forEach (b => println(b.name))
Bar1 <- Foo1
Bar2 <- Foo1
Bar3 <- Foo1
Bar1 <- Foo2
Bar2 <- Foo2
Bar3 <- Foo2
Bar1 <- Foo3
Bar2 <- Foo3
Bar3 <- Foo3

// IntStream.range(1, 4)
//     .mapToObj(i -> new Foo("Foo" + i))
//     .peek(f -> IntStream.range(1, 4)
//         .mapToObj(i -> new Bar("Bar" + i + " <- " f.name))
//         .forEach(f.bars::add))
//     .flatMap(f -> f.bars.stream())
//     .forEach(b -> System.out.println(b.name));
  // IntStream.range(1, 4).
  //   mapToObj(i => new Foo("Foo" + i)).
  //   peek(f => IntStream.range(1, 4).mapToObj(i => new Bar(s"Bar$i <- ${f.name}")).forEach(f.bars.add)).
  //   flatMap(_.bars.stream).
  //   forEach(b => println(b.name))

// class Outer { Nested nested; }
// class Nested { Inner inner; }
// class Inner { String foo; }

class Outer(var nested: Nested = null)
class Nested(var inner: Inner)
class Inner(var foo: String)

// Optional.of(new Outer())
//     .flatMap(o -> Optional.ofNullable(o.nested))
//     .flatMap(n -> Optional.ofNullable(n.inner))
//     .flatMap(i -> Optional.ofNullable(i.foo))
//     .ifPresent(System.out::println);

Optional.of(new Outer()).
  flatMap(o => Optional.ofNullable(o.nested)).
  flatMap(n => Optional.ofNullable(n.inner)).
  flatMap(i => Optional.ofNullable(i.foo)).
  ifPresent(println)

val none = new Outer()
val some = new Outer(new Nested(new Inner("foo")))
for {
  o   <- Option(some)
  n   <- Option(o.nested)
  i   <- Option(n.inner)
  foo <- Option(i.foo)
} println(foo)