Created by Oleg Prophet / @oregu_desu
03/18/2014 Last update: 5 Unofficial tagline:
public interface Sized { default boolean isEmpty() { return size() == 0; } int size(); }
class VeryFastCar extends ACar implements IFastCar, IFastSteerCar {} class VerySlowCar extends ACar implements ISlowCar, ISlowSteerCar {} // Even better would be (you can in Scala) ICar car = new ACar() with ISlowCar, IFastSteerCar;
Finally! Define static methods right in the interfaces.
How that makes you feel, huh?
Remove your Collections, Arrays, Paths now.
Reduce your boilerplate.
Set and List didn't change interface much, but let's lookup Collection and Iterable.
* We'll get to them in a moment.
Since mutability is evil, we replaced java.util.Date class with a bunch of immutable java.time.* classes!
“All the classes are immutable and thread-safe.”
void processStringLst(List<String> l) { ... } Lst.processStringLst(List.<String>empty());
Lst.processStringLst(List.empty());
String s = Lst.<String>singleton().head();
Meh…
More we'll see in lambda slides
List<String> names = new ArrayList<String>(); for (int i = 0; i < fields.size(); i++) { Field fld = fields.get(i); names.add(fld.getName()); } for (int i = 0; i < names.size(); i++) { String name = names.get(i); System.out.println(name); }
names = fields.stream().map(Field::getName).collect(toList()); names.forEach(System.out::println);
names.map((String s) -> { return s.length(); });
We know it's a collection of strings!
names.map((s) -> s.length());
That's not a LISP! Who likes parentheses anyway?
names.map(s -> s.length());
Can I have a method reference, please?
names.map(String::length);
Thank you, Java 8.
Object::toString
Field::create
Field::new
this::processField
a::process (a is some object in scope)
// Group employees by department Map<Department, List<Employee>> byDept = employees.stream().collect(groupingBy(Employee::getDepartment));
// Partition students into passing and failing Map<Boolean, List<Student>> passingFailing = students.stream().collect(partitioningBy( s -> s.getGrade() >= PASS_THRESHOLD));
// Classify people by state and city Map<String, Map<String, List<Person>>> peopleByStateAndCity = personStream.collect(groupingBy(Person::getState, groupingBy(Person::getCity)))
@FunctionalInterface public interface Function<T, R> { R apply(T t); }
Function<String, String> m = s -> s.toUpperCase(); Function<String, Integer> f = String::length; Function g = f.andThen(Integer::reverse);
Function id = Function.identity();
Function composition
f : X → Y
g : Y → Z
g ∘ f : X → Z
Function<String, Integer> f = String::length; Function<Integer, Float> g = Integer::floatValue; Function h = g.compose(f);
Function<String, UnaryOperator<String>> curried = s1 -> s2 -> s1.concat(" ").concat(s2); // Partial application UnaryOperator<String> hask = curried.apply("Haskell"); out.println(hask.apply("Curry")); out.println(hask.apply("Wexler"));
* Currying is a fancy name for schönfinkeling
Can't curry any function like (a, b) → a + b;
But we have tools:
public interface Fn { static <T,U,R> Function<T, Function<U,R>> curry(BiFunction<T,U,R> bi) { return t -> u -> bi.apply(t ,u); } static <T,U,R> Function<U,R> partial(BiFunction<T,U,R> bi, T t) { return u -> bi.apply(t ,u); } }
BiFunction<String, Integer, Float> bi = (s, i) -> (s.length() + i)/2.0f; // Can't do bi.apply("hello") for any bi Function<Integer, Float> part = Fn.partial(bi, "hello"); // Or: Function <Integer, Float> part = Fn.curry(bi).apply("hello"); // Will we be able to call part(10) someday? out.println(part.apply(10)); out.println(part.apply(22));
These are intermediate operations
They are all lazy.
These are terminal operations
They are not lazy at all.
No element will be produced until you call one of these.
* Collectors api: toList(), counting(), joining(), etc.
From sequential to parallel in the blink of an eye
lns = names.parallelStream().collect(groupingBy(String::length)); lns.forEach((key, ns) -> out.println(key + ":\t" + ns.stream().collect(joining(", "))));
findAny() returns special container object Optional
A convenient way to represent result absence.
(And reduce NPE count.)
No more PermGen space errors and PermGen tuning.
Java says:VM warning: ignoring option MaxPermSize=512m;support was removed in 8.0
Jon Masamitsu:
A goal for removing perm gen was so that users do not have to think about correctly sizing it.— But where are my class instances?
Native memory region for class data.
Grow automatically by default.
Garbage collected.
-XX:MetaspaceSize -XX:MaxMetaspaceSize
Transition to Java 8: e/Perm/Metaspace/g
— You said this is Hipster slides, but you didn't even mention a monad!
— Sorry guys. No monads until we'll have Higher Kinded Polymorphism in Java!
Thank you!