Beyond Lambdas, the aftermath @DanielSawano @DanielDeogun Spotify 2016
A presentation at Spotify Java Conference 2016 in April 2016 in Stockholm, Sweden by Daniel Sawano
 
                Beyond Lambdas, the aftermath @DanielSawano @DanielDeogun Spotify 2016
 
                About Us… Daniel Deogun Daniel Sawano Omegapoint Stockholm - Gothenburg - Malmoe - Umea - New York
 
                [insert code here]
 
                Optionals 1
7
final
Oracle oracle =
new
Oracle();
8
9   String _() {
10
final
Advise advise = currentAdvise();
11
12
if
(advise !=
null
) {
13
return
advise.cheap();
14      }
15
else
{
16
return
oracle.advise().expensive();
17      }
18  }
 
                Optionals 1
25
final
Oracle oracle =
new
Oracle();
26
27  String _() {
28
final
Advise advise = currentAdvise();
29
30
return
Optional.ofNullable(advise)
31                     .map(Advise::cheap)
32                     .orElse(oracle.advise().expensive());
33  }
 
                Optionals 1
25
final
Oracle oracle =
new
Oracle();
26
27  String _() {
28
final
Advise advise = currentAdvise();
29
30
return
Optional.ofNullable(advise)
31                     .map(Advise::cheap)
32                     .orElseGet( () ->
oracle.advise().expensive());
33  }
 
                Optionals 2
26  String _(
final
Optional<String> optOfSomeValue) {
27
28
return
optOfSomeValue.map(v -> calculate(v))
29                           .filter(someCriteria())
30                           .map(v -> transform(v))
31                           .orElseGet(() -> completelyDifferentCalculation());
32
33  }
 
                Optionals 2
26  String _(
final
Optional<String> optOfSomeValue) {
27
28
if
(optOfSomeValue.isPresent()) {
29
final
String calculatedValue = calculate(optOfSomeValue.get());
30
if
(someCriteria().test(calculatedValue)) {
31
return
transform(calculatedValue);
32          }
33      }
34
35
return
completelyDifferentCalculation();
36
37  }
 
                Optionals 2
26  String _() {
27
return
value()
28              .flatMap(v -> firstCalculation(v))
29              .orElseGet(() -> completelyDifferentCalculation());
30  }
31
32  Optional<String> value() {
33
return
Optional.of(someValue());
34  }
35
36  Optional<String> firstCalculation(
final
String v) {
37
return
Optional.of(calculate(v))
38                     .filter(someCriteria())
39                     .map(value -> transform(value));
40  }
 
                Optionals 3 27 <T> void _( final Optional<T> argument) { 28 argument.map(a -> doSomething(a)); 29 }
 
                Optionals 3
25  <T>
void
_(
final
T argument) {
26
if
(argument !=
null
) {
27          doSomething(argument);
28      }
29  }
 
                Optionals 3 26 <T> void _( final T argument) { 27 doSomething(notNull(argument)); 28 }
 
                Streams 1
30  @Test
31
public void
_() {
32
33
final
Stream<String> stream = elements().stream()
34                                              .sorted();
35
36
final
String result = stream.collect(joining(
","
));
37
38      assertEquals(
"A,B,C"
, result);
39
40  }
41
42
static
List<String> elements() {
43
return
asList(
"C"
,
"B"
,
null
,
"A"
);
44  }
 
                Streams 1
31  @Test
32
public void
_() {
33
34
final
Stream<String> stream = elements().stream()
35                                              .filter(Objects::nonNull)
36                                              .sorted();
37
38
final
String result = stream.collect(joining(
","
));
39
40      assertEquals(
"A,B,C"
, result);
41
42  }
43
44
static
List<String> elements() {
45
return
asList(
"C"
,
"B"
,
null
,
"A"
);
46  }
 
                Streams 2
27  @Test
28
public void
_() {
29
30
final long
idToFind =
6
;
31
final
Predicate<Item> idFilter = item -> item.id().equals(idToFind);
32
33      service().itemsMatching(idFilter)
34               .findFirst()
35               .ifPresent(Support::doSomething);
36
37  }
 
                Streams 2
28  @Test
29
public void
_() {
30
31
final long
idToFind =
6
;
32
final
Predicate<Item> idFilter = item -> item.id().equals(idToFind);
33
34      service().itemsMatching(idFilter)
35               .reduce(toOneItem())
36               .ifPresent(Support::doSomething);
37
38  }
39
40  BinaryOperator<Item> toOneItem() {
41
return
(item, item2) -> {
42
throw new
IllegalStateException(
"Found more than one item with the same id"
);
43      };
44  }
 
                Streams 3
29
private final
UserService userService =
new
UserService();
30
private final
OrderService orderService =
new
OrderService();
31
32  @Test
33
public void
_() {
34      givenALoggedInUser(userService);
35
36      itemsToBuy().stream()
37                  .map(item ->
new
Order(item.id(), currentUser().id()))
38                  .forEach(orderService::sendOrder);
39
40      System.out.println(format(
"Sent %d orders"
, orderService.sentOrders()));
41  }
42
43  User currentUser() {
44
final
User user = userService.currentUser();
45      validState(user !=
null
,
"No current user found"
);
46
return
user;
47  }
 
                Streams 3
29
private final
UserService userService =
new
UserService();
30
private final
OrderService orderService =
new
OrderService();
31
32  @Test
33
public void
_() {
34      givenALoggedInUser(userService);
35
36
final
User user = currentUser();
37      itemsToBuy().parallelStream()
38                  .map(item ->
new
Order(item.id(), user.id()))
39                  .forEach(orderService::sendOrder);
40
41      System.out.println(format(
"Sent %d orders"
, orderService.sentOrders()));
42  }
43
44  User currentUser() {
45
final
User user = userService.currentUser();
46      validState(user !=
null
,
"No current user found"
);
47
return
user;
48  }
 
                LAmbdas 1
28
static
Integer numberOfFreeApples(
final
User user,
29
final
Function<User, Integer> foodRatio) {
30
return
2
33
@Test
34
public void
_() {
35
36
final
Function<User, Integer> foodRatioForVisitors = u -> u.age() >
12
?
2
:
1
;
37
38
final int
numberOfFreeApples = numberOfFreeApples(someUser(), foodRatioForVisitors);
39
40 System.out.println(format( "Number of free apples: %d" , numberOfFreeApples)); 41
42 }
 
                LAmbdas 1
29  @Test
30
public void
_() {
31
32
final
Function<User, Integer> foodRatioForVisitors = u -> u.age() >
12
?
2
:
1
;
33
final
Function<User, Integer> age = User::age;
34
35
final int
numberOfFreeApples_1 = numberOfFreeApples(someUser(), foodRatioForVisitors);
36
final int
numberOfFreeApples_2 = numberOfFreeApples(someUser(), age);
// This is a bug!
37
38      System.out.println(format(
"Number of free apples (1): %d"
, numberOfFreeApples_1));
39      System.out.println(format(
"Number of free apples (2): %d"
, numberOfFreeApples_2));
40
41  }
 
                LAmbdas 1
28       @FunctionalInterface
29
interface
FoodRatioStrategy {
30
31           Integer ratioFor(User user);
32       }
33
34
static
Integer numberOfFreeApples(
final
User user,
35
final
FoodRatioStrategy ratioStrategy) {
36
return
2
39 @Test 40
public void _() { 41
42
final
FoodRatioStrategy foodRatioForVisitors = user -> user.age() >
12
?
2
:
1
;
43
final
Function<User, Integer> age = User::age;
44
45
final
Integer numberOfFreeApples_1 = numberOfFreeApples(someUser(), foodRatioForVisitors);
46
//final Integer numberOfFreeApples_2 = numberOfFreeApples(someUser(), age);
47
48 System.out.println(format( "Number of free apples (1): %d" , numberOfFreeApples_1)); 49 }
 
                LAmbdas 2
25  @Test
26
public void
should_build_tesla() {
27
28      assertEquals(
1000
,
new
TeslaFactory().createTesla().engine().horsepower());
29
30  }
31
32  @Test
33
public void
should_build_volvo() {
34
35      assertEquals(
250
,
new
VolvoFactory().createVolvo().engine().horsepower());
36
37  }
 
                LAmbdas 3
29  @Test
30
public void
_() {
31
32
final
List<Integer> values = asList(
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
);
33
34      allEvenNumbers(values);
35
36      System.out.println(
"Hello"
);
37
38  }
39
40
static
List<Integer> allEvenNumbers(
final
List<Integer> values) {
41
return
values.stream()
42                   .filter(Support::isEven)
43                   .collect(toList());
44  }
 
                LAmbdas 3
31  @Test
32
public void
_() {
33
34
final
List<Integer> values = asList(
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
);
35
36
final
Supplier<List<Integer>> integers = () -> allEvenNumbers(values);
37
38      System.out.println(integers.get());
39
40  }
41
42
static
List<Integer> allEvenNumbers(
final
List<Integer> values) {
43
return
values.stream()
44                   .filter(Support::isEven)
45                   .collect(toList());
46  }
 
                LAmbdas 4
24
private final
String pattern;
25
26
public
_14(
final
String pattern) {
27
this
.pattern = pattern;
28  }
29
30
public
List<String> allMatchingElements(
final
List<String> elements) {
31
return
elements.stream()
32                     .filter(e -> e.contains(pattern))
33                     .collect(toList());
34  }
 
                LAmbdas 4
25
private final
String pattern;
26
27
public
_14(
final
String pattern) {
28
this
.pattern = pattern;
29  }
30
31
public
List<String> allMatchingElements(
final
List<String> elements) {
32
return
elements.stream()
33                     .filter(matches(pattern))
34                     .collect(toList());
35  }
36
37
private
Predicate<String> matches(
final
String pattern) {
38
return
e -> e.contains(pattern);
39  }
 
                Q & A [Questions]
 
                Code examples can be found here: https://github.com/sawano/beyond-lambdas-the-aftermath
 
                Thank you! @DanielSawano @DanielDeogun
