Writing beautiful code with Java 8
-
Upload
sergiu-mircea-indrie -
Category
Software
-
view
54 -
download
2
Transcript of Writing beautiful code with Java 8
![Page 2: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/2.jpg)
Disclaimer
This is not a clean code presentation, but rather a code esthetics oriented presentation which may include clean code.
![Page 3: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/3.jpg)
Beautiful code?
● Easy to read/understand/write● Concise● DSL-like● Clean code ++
![Page 4: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/4.jpg)
Ugly vs Beautiful
for (int i = 0; i < meetings.size(); i++) {
System.out.println(meetings);
}
for (Meeting meeting : meetings) {
System.out.println(meeting);
}
meetings.forEach(System.out::println);
![Page 5: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/5.jpg)
Ugly vs Beautiful
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Complex stuff");
}
}).start();
new Thread(() -> System.out.println("Complex stuff")).start();
![Page 6: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/6.jpg)
Ugly vs Beautiful
Map<String, List<Meeting>> meetingsById = meetings.stream()
.collect(Collectors.groupingBy(Meeting::getId));
Map<String, List<Meeting>> meetingsGrouped = new HashMap<>();
for (Meeting meeting : meetings) {
if (!meetingsGrouped.containsKey(meeting.getId())) {
meetingsGrouped.put(meeting.getId(), new ArrayList<>());
}
meetingsGrouped.get(meeting.getId()).add(meeting);
}
![Page 7: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/7.jpg)
Ugly vs Beautiful
// guarded logging
if (logger.isDebugEnabled()) {
logger.debug("This {} and {} with {} ", 1, that, compute());
}
VS
logger.debug("This {} ", () -> compute());
![Page 8: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/8.jpg)
What’s “new” in Java 8?
● LambdasRunnable r2 = () -> System.out.println("Hello world two!");
● StreamsList<Room> rooms = microsoftExchangeService.getRoomLists().getItems().parallelStream()
.filter(this::isValidRoomList)
.map(this::retrieveRoomsInRoomList)
.flatMap(List::stream)
.collect(Collectors.toList());
● OptionalOptional<Meeting> meeting = meetingsDao.findById(meetingId);
meeting.ifPresent(this::setMeetingAsManuallyEnded);
![Page 9: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/9.jpg)
PS - Help from IDEA
● Migration suggestions (more to come in IDEA 2016.3)
![Page 10: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/10.jpg)
Enemy #1: Checked Exceptions
private static void checkedException() {
List<String> strings = Arrays.asList(1, 2, 3, 4, 5).stream()
.map(Exceptions::intToString)
.collect(Collectors.toList());
System.out.println(strings);
}
private static String intToString(Integer number) throws Exception {
if (number == 3) {
throw new Exception("wrong number, pal!");
}
return String.valueOf(number);
}
![Page 11: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/11.jpg)
Enemy #1: Checked Exceptions
● Complex issue (see Brian Goetz’s post from 2010)○ generic type parameters are monadic ⇒ one exact type○ throws clauses are variadic ⇒ 0 or more types
● Solution?
![Page 12: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/12.jpg)
Enemy #1: Checked Exceptions - Solution
● 1st Solution - Unchecked Exceptions*● 2nd Solution - Wrap to 1st (see org.jooq.lambda.Unchecked)
public static <T> T unchecked(Callable<T> callable) {
try {
return callable.call();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
List<Room> rooms = roomAddresses.parallelStream()
.map(room -> unchecked(() -> getRoomWithoutMeetings(room)))
.collect(Collectors.toList());
* Python, Scala, C#, Ruby, PHP … don’t have checked exceptions
![Page 13: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/13.jpg)
Enemy #1: Checked Exceptions - Solution
public static <T> T unchecked(Callable<T> callable) {
try {
return callable.call();
} catch (ApiServiceException e) {
throw new ApiServiceRuntimeException(e);
} catch (Exception e) {
throw runtime(e);
}
}
private static RuntimeException runtime(Throwable e) {
if (e instanceof RuntimeException) {
return (RuntimeException) e;
}
return new RuntimeException(e);
}
![Page 14: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/14.jpg)
Enemy #1: Checked Exceptions - Solution
● A more functional approach
![Page 15: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/15.jpg)
Enemy #1: Checked Exceptions - Solution
● A more functional approach
String complexResult = Try.of(SomeClass::dangerousGet)
.recover(x -> Match(x).of(
Case(instanceOf(IllegalStateException.class), () -> "1st exception"),
Case(instanceOf(IllegalArgumentException.class), () -> "2nd exception")
))
.getOrElse("default2");
![Page 16: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/16.jpg)
By the way
Java 9 brings: Collection Factory Methods* (all immutable)
+ some stream improvements like iterate, take/dropWhile
* Nevermind if you’ve been using Guava, jOOQ
![Page 17: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/17.jpg)
Java 8 is nice, but don’t
// long lambdas
numbers.forEach(e -> {
int count = 0;
for(int i = 1; i <= e; i++) {
if(e % i == 0) count++;
}
System.out.println(count);
});
// unformatted streams
List<String> strings = Arrays.asList(1, 2, 3).stream().map(Object::toString)
.map(String::toUpperCase).limit(5).collect(Collectors.toList());
![Page 18: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/18.jpg)
Java 8 is nice, but
Java 8 Computation Style
![Page 19: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/19.jpg)
Level up: Javaslang
// Java 8
List<Integer> integers = Arrays.asList(1, 2, 3, 4);
List<Integer> evenNumbers = integers.stream()
.filter(nr -> nr % 2 == 0)
.collect(Collectors.toList());
// Javaslang
List<Integer> integers = List.of(1, 2, 3, 4);
List<Integer> evenIntegers = integers.filter(nr -> nr % 2 == 0);
* javaslang.collection.List
![Page 20: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/20.jpg)
Level up: Javaslang
● “...greatly inspired by Scala”
● Hence very functional
● facilitates functional programming through immutability
![Page 21: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/21.jpg)
List<Integer> integers = Arrays.asList(1, 2, 3, 4);
● List is really javaslang.collection.List :) but we do have toJavaList/Array/Collection/Set() etc.
public interface List<T> extends Kind1<List<?>, T>, LinearSeq<T>, Stack<T> {
default java.util.List<T> toJavaList() {
return ValueModule.toJavaCollection(this, new ArrayList<>());
}
● All Javaslang collections are Iterable and thus can be used in enhanced for-statements
for (String s : List.of("Java", "Advent")) {
// side effects and mutation
}
Level up: Javaslang
![Page 22: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/22.jpg)
● Functional exception handling
// no need to handle exceptions
Try.of(SomeClass::bunchOfWork).getOrElse("default");
String complexResult = Try.of(SomeClass::dangerousGet)
.recover(x -> Match(x).of(
Case(instanceOf(IllegalStateException.class), () -> "1st exception"),
Case(instanceOf(IllegalArgumentException.class), () -> "2nd exception")
))
.getOrElse("default2");
Level up: Javaslang
![Page 23: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/23.jpg)
● Lazy
Lazy<Double> lazy = Lazy.of(Math::random);
lazy.isEvaluated(); // = false
lazy.get(); // = 0.123 (random generated)
lazy.isEvaluated(); // = true
lazy.get(); // = 0.123 (memoized)
● + other FP features like function composition, currying, memoization, lifting, immutable collections, tuples
Level up: Javaslang
![Page 24: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/24.jpg)
Or maybe just switch to Scala :D
// type inference, nice constructors, native streams API, no semicolons :)
val integers = List(1, 2, 3, 4)
val evenIntegers = integers.filter(_ % 2 == 0)
// pre/post/infix operators
val sum = (1 to 10).sum
// immutable, generated equals/getter/toString/hashcode, pattern matching decomposition
case class Person(firstName: String, lastName: String)
object Singleton {}
// immutable collections, XML processing, multiple inheritance, tuples, REPL etc.
![Page 25: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/25.jpg)
Or maybe just switch to Scala :D
// pattern matching & decomposition
object Demo {
def main(args: Array[String]) {
val alice = new Person("Alice", 25)
val charlie = new Person("Charlie", 32)
for (person <- List(alice, charlie)) {
person match {
case Person("Alice", 25) => println("Hi Alice!")
case Person(name, age) => println(
"Age: " + age + " year, name: " + name + "?")
}
}
}
case class Person(name: String, age: Int)
}
![Page 26: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/26.jpg)
References
https://github.com/tedyoung/awesome-java8https://blog.jooq.org/2014/05/02/java-8-friday-lets-deprecate-those-legacy-libs/https://blog.jetbrains.com/idea/2016/07/java-8-top-tips/http://blog.agiledeveloper.com/2015/06/lambdas-are-glue-code.htmlhttps://garygregory.wordpress.com/2015/09/16/a-gentle-introduction-to-the-log4j-api-and-lambda-basics/https://dzone.com/articles/java-8-functional-interfaces-0http://openjdk.java.net/jeps/269https://blogs.oracle.com/briangoetz/entry/exception_transparency_in_javahttp://www.artima.com/intv/handcuffs.htmlhttp://www.mindview.net/Etc/Discussions/CheckedExceptionshttps://github.com/jOOQ/jOOL#orgjooqlambdauncheckedhttp://iteratrlearning.com/java9/2016/08/06/java9-streams.htmlhttp://www.javaslang.io/http://www.scala-lang.org/
![Page 27: Writing beautiful code with Java 8](https://reader036.fdocuments.us/reader036/viewer/2022062316/587820c41a28aba12d8b6767/html5/thumbnails/27.jpg)
That’s all folks!