Does Java Have a Future After Version 8? (Belfast JUG April 2014)

Post on 06-May-2015

195 views 0 download

Tags:

description

Presented to the Belfast Java User Group in April 2014 this talk explores if the changes made to Java in version 8 are enough to keep it the dominant programming platform.

Transcript of Does Java Have a Future After Version 8? (Belfast JUG April 2014)

Belfast JUG

April 2014

About Me

Goals of this Talk…

Everything Depends on Context…

Some Thoughts from React

Some Thoughts from React 2014 Architecture is back in fashion

No more ‘just use the stack’ or ‘wait for speedup’ Design so there is no bottleneck Be ready for the ‘Internet of Things’

The same lessons apply at different levels Key concepts:

Actors, Futures, Reactive Extensions (RX) Eventually consistent data storage Convergent replicated data types Coding becomes increasingly declarative Send code to data and ensure ‘data knows where to go’

A Metaphor…

Why Are We Still Using Rockets?

The Origins Of Rockets

The Killer-App for Rockets…

Mutually Assured Destruction

The Commercial Payoff

Only Rockets Will Be Insured

From the late 1950's until the early 1980's, the ownership and operation of satellites was generally undertaken only by government agencies like National Aeronautics and Space Administration (NASA) and the European Space Agency (ESA). While commercial satellite insurance has been available since 1964, very little was purchased until the mid 1980's because government agencies generally self-insure the risk. Starting in the early 1980's, the commercial satellite industry began to take off and with it came the increased need for satellite insurance since commercial enterprises are not ordinarily willing to self-insure such high valued assets that are subject to relatively high loss frequencies. Market capacity soared in the 1990's, from around $300 million in 1990 to almost $1.2 billion in 1999, 3 well in excess of the $175 to $250 million of coverage required for most satellites. Occasionally a satellite may require as much as $400 million of coverage.

Estimating Satellite Insurance Liabilities Allen J. Gould and Orin M. Linden

The Origins of Java

The Killer App for Java

The Law of the Server Farm

We Are Locked Into Java!!

What is the JVM Today?

What About .NET?

What About The Others…

Ruby on Rails Node.js Django etc…

What About the Others?

You came close but you never made it. And if you were gonna make it, you would have

made it before now…

The Perfect Language…

A Newsflash…

Object Orientation Works!!!

The Horsemen of the Javapocalypse…

InnerClasses

Non-ReifiedGenerics

CheckedExceptions

ValueTypes

The Road Not Taken…The newest version of the Microsoft Visual J++ development environment supports a language construct called delegates or bound method references…

It is unlikely that the Java programming language will ever include this construct. Sun already carefully considered adopting it in 1996, to the extent of building and discarding working prototypes. Our conclusion was that bound method references are unnecessary and detrimental to the language…

We believe bound method references are unnecessary because another design alternative, inner classes, provides equal or superior functionality. In particular, inner classes fully support the requirements of user-interface event handling, and have been used to implement a user-interface API at least as comprehensive as the Windows Foundation Classes. We believe bound method references are harmful because they detract from the simplicity of the Java programming language and the pervasively object-oriented character of the APIs….

Extracts From: About Microsoft’s “Delegates" Whitepaper by the Java language team at JavaSoft

Our Industry Has Issues…

We Stayed!! (and fixed the bugs…)

Our Industry Has Issues…

Our Industry Has Issues…

Our Industry Has Issues…

The Proposition:Work till 2 am for 20 years,

hunting bugs fuelled by cold

pizza and warm coke.

The Rewards:Kudos from peers

Detach from ‘civilian’ life

Grow neckbeard

Present at QCon

Our Industry Has Issues…

The Solution…

AdoptAgile!

(duh)

Agile Values

Feedback cycles Working as a team Universal ownership Sustainable pace Asking for assistance Clear prioritization Retrospectives No prima-donnas

That he which hath no stomach to this fight, Let him depart; his passport shall be made, And crowns for convoy put into his purse; We would not die in that man's company...From this day to the ending of the world, But we in it shall be remembered- We few, we happy few, we band of brothers;

The Challenge

A Solution? Add FP to Java???

The Solutionpublic class Program { public static void main(String [] args) { List<Integer> input = Arrays.asList(30,26,22,18,14,10); input.stream() .parallel() .map(Program::waitAndReturn) .forEach(System.out::println); } private static String waitAndReturn(Integer sleep) { goToSleep(sleep); return buildMessage(sleep); }

The Solution

private static void goToSleep(Integer sleep) { try { Thread.sleep(sleep * 1000); } catch (InterruptedException ex) { System.out.println("BANG! " + ex.getMessage()); } } private static String buildMessage(Integer sleep) { String msg = "Thread %d just returned after waiting %d secs"; long threadId = Thread.currentThread().getId(); return String.format(msg, threadId, sleep); }}

The Solution

Thread 11 just returned after waiting 10 secsThread 13 just returned after waiting 14 secsThread 1 just returned after waiting 18 secsThread 14 just returned after waiting 22 secsThread 10 just returned after waiting 26 secsThread 12 just returned after waiting 30 secs

public class Program { public static void main(String [] args) { List<Integer> input = Arrays.asList(30,26,22,18,14,10); input.stream() .parallel() .map(Program::waitAndReturn) .forEach(System.out::println); } …

Thread 1 just returned after waiting 30 secsThread 1 just returned after waiting 26 secsThread 1 just returned after waiting 22 secsThread 1 just returned after waiting 18 secsThread 1 just returned after waiting 14 secsThread 1 just returned after waiting 10 secs

The Functional Toolkit

Lambdas Method References Optional Monad Streams (new style) And also:

Implementations allowed in interfaces

New data / time library

Lambdas

Supplier<String> ref1 = () -> "Scooby";

Consumer<String> ref2 = s -> System.out.println(s);

Function<String,Integer> ref3 = s -> s.length();

IntToDoubleFunction ref4 = num -> num * 1.0;

Predicate<String> ref5 = s -> s.length() == 5;

UnaryOperator<String> ref6 = s -> s + "wobble";

BinaryOperator<String> ref7 = (s1,s2) -> s1 + s2;

Converter<String,Double> ref8 = s -> Double.parseDouble(s);

@FunctionalInterfacepublic interface Converter<T,U> { public U convert(T input);}

Lambdas

//Never write multi-line lambdas!Consumer<String> ref9 = (s) -> { System.out.println(ref1.get()); ref2.accept(s); System.out.println(ref3.apply(s)); System.out.println(ref4.applyAsDouble(123)); System.out.println(ref5.test(s)); System.out.println(ref6.apply(s)); System.out.println(ref7.apply(s, "wobble")); System.out.println(ref8.convert("1234.567")); };ref9.accept("wibble");

Scoobywibble6123.0falsewibblewobblewibblewobble1234.567

Method References

void demoStaticMethodRefs() { Supplier<Double> ref1 = Math::random; Supplier<Thread> ref2 = Thread::currentThread; DoubleUnaryOperator ref3 = Math::sqrt; UnaryOperator<String> ref4 = System::getProperty; System.out.println(ref1.get()); System.out.println(ref2.get().getId()); System.out.println(ref3.applyAsDouble(16.0)); System.out.println(ref4.apply("java.vm.vendor"));} 0.2960393385581157

14.0Oracle Corporation

Method References

void demoInstanceMethodRefs() throws Exception { StringBuilder builder = new StringBuilder(); InetAddress address = InetAddress.getByName("localhost"); File currentDir = new File("."); Function<String,StringBuilder> ref1 = builder::append; Supplier<String> ref2 = address::getCanonicalHostName; Supplier<String> ref3 = currentDir::getAbsolutePath; Consumer<Object> out = System.out::println; out.accept(ref1.apply("def")); out.accept(ref2.get()); out.accept(ref3.get());}

deflocalhost/Users/ggilmour/JavaEightDemos/.

Method References

void demoConstructorRefs() throws Exception { Function<String,File> ref1 = File::new; Function<URI,File> ref2 = File::new; File f1 = ref1.apply("."); File f2 = ref2.apply(new URI("file:///bin")); System.out.println(f1.getAbsolutePath()); System.out.println(f2.getAbsolutePath());}

/Users/ggilmour/JavaEightDemos/./bin

Optional

private static Optional<String> fetchSystemProperty(String name) { String result = System.getProperty(name); if(result == null) { return Optional.empty(); } else { return Optional.of(result); }}

EmptySet

Set of 1

Optional

public static void main(String [] args) { Optional<String> result1 = fetchSystemProperty("java.version"); Optional<String> result2 = fetchSystemProperty("wibble"); result1.ifPresent(s -> System.out.println(s)); result2.ifPresent(s -> System.out.println(s));

result1.ifPresent(System.out::println); result2.ifPresent(System.out::println);

System.out.println(result1.orElse("No such property!")); System.out.println(result2.orElse("No such property!"));}

Streams

System.out.println("\t" + data.stream().findAny().orElse("Empty!"));if(data.stream().allMatch(s -> s.length() > 1)) { System.out.println("\tAll strings longer than 1");}if(data.stream().anyMatch(s -> s.length() > 3)) { System.out.println("\tAt least one string longer than 3");}if(data.stream().noneMatch(s -> s.length() > 4)) { System.out.println("\tNo strings longer than 4");}

Streams

data.stream().forEach(s -> System.out.printf("%s ",s));

Stream<String> results = data.stream().filter(s -> s.length() == 3);

Stream<Integer> results1 = data.stream().map(s -> s.length());IntStream results2 = data.stream().mapToInt(s -> s.length());LongStream results3 = data.stream().mapToLong(s -> s.length());DoubleStream results4 = data.stream().mapToDouble(s -> s.length() * 1.0);

Optional<String> result1 = data.stream().reduce((s1,s2) -> s1 + "-" + s2);StringBuilder result2 = data.stream()

.reduce(new StringBuilder(), (sb,s) -> sb.insert(0,s), (sb1,sb2) -> sb1);

int result3 = data.stream().reduce(0, (total,s) -> total + s.codePointAt(0), (a,b) -> a + b );

Scala is simpler than Java 8

The Problem

“super”

“cala”

“fragil”

“istic”

“expy”

“ali”

“dotious”

S U P E R C A L A F R A G I L I S T I C E X P Y A L I D O T I O U S

?

The Theoretical Solution

S U P E R

C A L A

I S T I C

F R A G I L

E X P Y

A L I

D O T I O U S

flatMap(String char [ ])

The Solution in Scala

object Program {def main(args : Array[String]) {

val data = Array("super","cala","fragil","istic","expy","ali","dotious")val result = data.flatMap(_.toCharArray)

for(c <- result) { printf(" %s", c);}

}}

s u p e r c a l a f r a g i l i s t i c e x p y a l i d o t i o u s

The Solution in Java (Part 1)

© Garth Gilmour 2011

import static java.util.Arrays.*;

public class Program { public static void main(String [] args) { String [] data = {"super","cala","fragil","istic","expy","ali","dotious"}; data.flatMap(s -> null); }}

The Solution in Java (Part 2)

import static java.util.Arrays.*;

public class Program { public static void main(String [] args) { String [] data = {"super","cala","fragil","istic","expy","ali","dotious"}; asList(data).flatMap(s -> null); }}

The Solution in Java (Part 3)

import static java.util.Arrays.*;

public class Program { public static void main(String [] args) { String [] data = {"super","cala","fragil","istic","expy","ali","dotious"}; asList(data).stream().flatMap(s -> null); }}

The Solution in Java (Part 4)

asList(data).stream().flatMap(s -> s.toCharArray());

The Solution in Java (Part 4)

The Solution in Java (Part 5)

Stream<char[]> results = asList(data).stream().flatMap(s -> asList(s.toCharArray()).stream());

for(Object obj : results.toArray()) { System.out.printf("%s ",obj);}

[C@5caf905d [C@27716f4 [C@8efb846 [C@2a84aee7 [C@a09ee92 [C@30f39991 [C@452b3a41

The Solution in Java (Part 5)

The Solution in Java (Part 5)

Stream<char[]> results = asList(data).stream().flatMap(s -> stream(s.toCharArray()));

The Solution in Java (Part 6)

import java.util.Arrays;import java.util.stream.Stream;

public class MyUtils { public static Stream toStream(String input) { Character[] output = new Character[input.length()]; for (int i = 0; i < input.length(); i++) { output[i] = input.charAt(i); } return Arrays.stream(output); } }

The Solution in Java (Part 6)import static java.util.Arrays.asList;import java.util.stream.Stream;

public class Program { public static void main(String [] args) { String [] data = {"super","cala","fragil","istic","expy","ali","dotious"}; Stream<char[]> results = asList(data).stream().flatMap(MyUtils::toStream); for(Object obj : results.toArray()) { System.out.printf("%s ",obj); } }}

s u p e r c a l a f r a g i l i s t i c e x p y a l i d o t i o u s

Is Java 8 More Complex?

Is NOT about absolute complexity Its about accidental vs. essential complexity Scala has higher essential complexity

But all the features ‘hang together’ You don’t have to meet it all at once

Is Java 8 More Complex?

Primitive types and boxing and arrays and collections and non-reified generics and var-args and lambdas and method refs. Oh My!

Can Java Be More Complex?

What About Clojure?

What About Haskell?

Looking Into The Future…

Watch this Presentation

Iterator(stream of items)

Observer(stream of events)

The Same (FP) Operators Apply!!(Filter, Map, Take, Reduce etc… )

RX

public class Item { public Item(int delay,

String message, Severity severity) {

this.delay = delay; this.message = message; this.severity = severity; } public int getDelay() { return delay; } public String getMessage() { return message; } public Severity getSeverity() { return severity; } private final int delay; private final String message; private final Severity severity; }

public enum Severity { HIGH, LOW}

public class MyObservable implements Observable.OnSubscribe<Item> { @Override public void call(Subscriber<? super Item> subscriber) { for(int i=0;i<100;i++) { int delay = (int)(Math.random() * 1000); String message = "Message " + i; Severity severity = (i % 2 == 0) ? Severity.HIGH : Severity.LOW; try { Thread.sleep(delay); subscriber.onNext(new Item(delay,message,severity)); } catch(InterruptedException ex) { subscriber.onError(ex); } } subscriber.onCompleted(); }}

public class Program { public static void main(String [] args) { demo1(Observable.create(new MyObservable())); printSpacer(); demo2(Observable.create(new MyObservable())); printSpacer(); demo3(Observable.create(new MyObservable())); } public static void printSpacer() { System.out.println("----------------------"); } public static void demo1(Observable<Item> observable) { observable.filter(item -> item.getSeverity() == HIGH) .map(item -> item.getMessage()) .subscribe(System.out::println); }

public static void demo2(Observable<Item> observable) { observable.reduce(0.0, (a,b) -> a + b.getDelay()) .subscribe(System.out::println); } public static void demo3(Observable<Item> observable) { observable.skip(20) .takeWhile(item -> !item.getMessage().endsWith("70")) .subscribe(item -> System.out.println(item.getMessage())); }}

Message 0Message 2Message 4Message 6Message 8Message 10Message 12Message 14Message 16LOTS MORE…Message 84Message 86Message 88Message 90Message 92Message 94Message 96Message 98

----------------------47412.0----------------------

Message 20Message 21Message 22Message 23Message 24Message 25Message 26Message 27Message 28LOTS MORE…Message 62Message 63Message 64Message 65Message 66Message 67Message 68Message 69

Concluding Thought

Its not about making everything scalable today. Its about opening the door to making arbitrary things scalable tomorrow, and enabling that decision to be transparent to the user of the service…

Thanks for Watching!

garth.gilmour@instil.co@GarthGilmour@instilhttps://www.facebook.com/instilireland