Michał Urbanek
“Java is still not dead -
and people are starting to figure that out.”
public interface Sized {
int size();
default boolean isEmpty() {
return size() == 0;
}
}
interface Iterator<T> {
boolean hasNext();
T next();
default void remove() {
throw new UnsupportedOperationException();
}
}
Class can extend only from one abstract class, but a class can implement multiple interfaces.
Abstract class can enforce a common state trough instance variables (fields). An interface can't have instance variables.
List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return b.compareTo(a);
}
});
Thread t = new Thread(new Runnable() {
public void run() {
System.out.println("Hello world");
}
});
List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
Collections.sort(names, (String a, String b) -> {
return b.compareTo(a);
});
Thread t = new Thread(new Runnable() {
public void run() {
System.out.println("Hello world");
}
});
List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return b.compareTo(a);
}
});
List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
Collections.sort(names, (String a, String b) -> b.compareTo(a));
List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
Collections.sort(names, (a, b) -> b.compareTo(a));
List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
names.sort((a, b) -> b.compareTo(a));
Thread t = new Thread(() -> { System.out.println("Hello world"); });
Thread t = new Thread(() -> System.out.println("Hello world"));
(String s) -> s.length
(Apple a) -> a.getWeight() > 150
() -> 42
(int x, int y) -> {
System.out.println("Result:");
System.out.println(x + y);
}
(parameters) -> expression
(parameters) -> { statements; }
if (logger.isDebugEnabled()) {
loger.debug("Cause: " + generateDiagnostics());
}
loger.debug(() -> "Cause: " + generateDiagnostics());
@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
}
Predicate<T> | T -> boolean |
Consumer<T> | T -> void |
Function<T, R> | T -> R |
Supplier<T> | () -> T |
UnaryOperator<T> | T -> T |
BinaryOperator<T> | (T, T) -> T |
BiPredicate<L, R> | (L, R) -> boolean |
Collection | Stream |
---|---|
Egarly Constructed | Computed on demand |
Values spread out in space | Values spread out in time |
Traversable many times | Traversable only once |
External iteration | Internal iteration |
Intermediate | Stream |
---|---|
Return Stream | Produce result |
Lazy | Eager |
Can be chained | Final |
e.g. filter, map, limit, sorted, distinct | e.g. forEach, count, collect, sum, min |
Simply change stream() to parallelStream()
animals.stream().filter(Animal::isPredator).count()
animals.parallelStream().filter(Animal::isPredator).count()
and let your extra cores do the job!!
Always measure!
Optional.empty();
Optional.of("Just a text");
Optional.ofNullable("This can be null");
Creation
Optional<String> optional = Optional.of("String");
optional.isPresent();
optional.ifPresent(s -> System.out.println(s));
optional.map(String::length).get();
optional.filter(s -> s.length() > 3).orElse("Default");
optional.orElseGet(() -> "Default");
optional.orElseThrow(() -> new IllegalArgumentException());
Operations
private String getInsuranceName(Person person) {
if (person != null) {
Car car = person.getCar();
if (car != null) {
Insurance insurance = car.getInsurance();
if (insurance != null) {
String name = insurance.getName();
return name == null ? UNKNOWN_NAME : name;
}
}
}
return UNKNOWN_NAME;
}
Null checks made easy
private String getInsuranceNameOptional(Person person) {
return Optional.ofNullable(person)
.flatMap(Person::getCarOptional)
.flatMap(Car::getInsuranceOptional)
.map(Insurance::getName)
.orElse(UNKNOWN_NAME);
}
Map<Integer, String> map = new HashMap<>();
// put value only if not already in map
map.putIfAbsent(5, "val5");
// iterate over entries
map.forEach((key, val) -> System.out.println(val));
// compute new value from old value
map.computeIfPresent(3, (key, val) -> key + num);
// compute new value only if not already in map
map.computeIfAbsent(23, key -> "val" + key);
// remove key only if given value
map.remove(3, "val3");
int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// sort array in parallel
Arrays.parallelSort(array);
// fill array with computed values in parallel
Arrays.parallelSetAll(array, i -> array.length - i);
// compute array's prefixes in parallel
Arrays.parallelPrefix(array, Integer::sum);
// access to the current date and time (timezone aware)
Clock clock = Clock.systemDefaultZone();
long millis = clock.millis();
// access to timezones
ZoneId.getAvailableZoneIds();
ZoneId.of("Europe/Berlin");
// time representation
LocalTime now = LocalTime.now(zone1);
LocalTime late = LocalTime.of(23, 59, 59);
now.isBefore(late);
long hoursBetween = ChronoUnit.HOURS.between(now, late);
// date representation
LocalDate today = LocalDate.now();
LocalDate yesterday = today.minusDays(1);
// date and time representation
LocalDateTime sylvester = LocalDateTime.of(2014, Month.DECEMBER, 31, 23, 59, 59);
DayOfWeek dayOfWeek = sylvester.getDayOfWeek();
DateTimeFormatter.ofPattern("MMM dd, yyyy - HH:mm").format(sylvester);
List<String> result = IntStream.range(0, 4)
.mapToObj(i -> CompletableFuture.supplyAsync(
() -> Computation.compute(i), executor))
.map(future -> future.thenApply(String::valueOf))
.map(future -> future.thenCompose(
s -> CompletableFuture.supplyAsync(() -> "value" + s, executor)))
.map(CompletableFuture::join)
.collect(Collectors.toList());