Add java8-features module: runnable demos and captured output for the ankurm.com java8-features article
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
/** Default and static interface methods, and the diamond that forces you to choose. */
|
||||
public class DefaultMethodsDemo {
|
||||
interface Walker { default String move() { return "walk"; } }
|
||||
interface Swimmer { default String move() { return "swim"; } }
|
||||
static class Duck implements Walker, Swimmer {
|
||||
// without this override the class does not compile: "types Walker and Swimmer are incompatible"
|
||||
public String move() { return Walker.super.move() + " + " + Swimmer.super.move(); }
|
||||
}
|
||||
interface Greeter {
|
||||
String name();
|
||||
default String greet() { return "Hello, " + name(); }
|
||||
static Greeter of(String n) { return () -> n; }
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
System.out.println("diamond resolved: " + new Duck().move());
|
||||
System.out.println("default + static: " + Greeter.of("Ankur").greet());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import java.util.function.*;
|
||||
|
||||
/** The core java.util.function interfaces and composition. */
|
||||
public class FunctionalInterfacesDemo {
|
||||
public static void main(String[] args) {
|
||||
Function<Integer, Integer> doubler = x -> x * 2;
|
||||
Function<Integer, Integer> plusOne = x -> x + 1;
|
||||
System.out.println("andThen : " + doubler.andThen(plusOne).apply(5));
|
||||
System.out.println("compose : " + doubler.compose(plusOne).apply(5));
|
||||
Predicate<String> empty = String::isEmpty;
|
||||
System.out.println("negate : " + empty.negate().test("abc"));
|
||||
Supplier<String> s = () -> "supplied";
|
||||
System.out.println("Supplier : " + s.get());
|
||||
BiFunction<Integer, Integer, Integer> add = Integer::sum;
|
||||
System.out.println("BiFunction : " + add.apply(3, 4));
|
||||
UnaryOperator<String> up = String::toUpperCase;
|
||||
System.out.println("UnaryOperator : " + up.apply("ok"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import java.util.*;
|
||||
import java.util.function.*;
|
||||
|
||||
/** Lambdas: the old anonymous-class way, the lambda way, a method reference, and what "effectively final" means. */
|
||||
public class LambdaDemo {
|
||||
public static void main(String[] args) {
|
||||
List<String> names = Arrays.asList("Meera", "Ankur", "Zoya", "Bhaskar");
|
||||
|
||||
// Java 7 style
|
||||
Collections.sort(names, new Comparator<String>() {
|
||||
@Override public int compare(String a, String b) { return a.length() - b.length(); }
|
||||
});
|
||||
System.out.println("anonymous class : " + names);
|
||||
|
||||
// Java 8 lambda, then a method reference
|
||||
names.sort((a, b) -> a.compareTo(b));
|
||||
System.out.println("lambda : " + names);
|
||||
names.sort(String::compareToIgnoreCase);
|
||||
System.out.println("method reference: " + names);
|
||||
|
||||
// capture: the local variable must be effectively final
|
||||
int base = 10;
|
||||
Function<Integer, Integer> addBase = x -> x + base;
|
||||
System.out.println("captured base : " + addBase.apply(5));
|
||||
|
||||
// 'this' inside a lambda is the enclosing object, not the lambda
|
||||
new LambdaDemo().thisDemo();
|
||||
}
|
||||
|
||||
void thisDemo() {
|
||||
Runnable lambda = () -> System.out.println("lambda this : " + this.getClass().getSimpleName());
|
||||
Runnable anon = new Runnable() {
|
||||
public void run() { System.out.println("anonymous this : " + this.getClass().getName()); }
|
||||
};
|
||||
lambda.run();
|
||||
anon.run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import java.util.*;
|
||||
|
||||
/** Optional: the null-chain it replaces, map/orElse, and the orElse vs orElseGet trap. */
|
||||
public class OptionalDemo {
|
||||
static String lookup(String key) { return "k1".equals(key) ? "value-1" : null; }
|
||||
static String expensive() { System.out.println(" expensive() called"); return "fallback"; }
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("present : " + Optional.ofNullable(lookup("k1")).map(String::toUpperCase).orElse("none"));
|
||||
System.out.println("absent : " + Optional.ofNullable(lookup("k2")).map(String::toUpperCase).orElse("none"));
|
||||
|
||||
System.out.println("orElse (value present):");
|
||||
Optional.of("x").orElse(expensive());
|
||||
System.out.println("orElseGet (value present):");
|
||||
Optional.of("x").orElseGet(OptionalDemo::expensive);
|
||||
|
||||
try { Optional.empty().get(); } catch (NoSuchElementException e) { System.out.println("get() on empty : " + e.getMessage()); }
|
||||
try { Optional.of(null); } catch (NullPointerException e) { System.out.println("Optional.of(null): NullPointerException"); }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import java.util.*;
|
||||
import java.util.stream.*;
|
||||
|
||||
/** Streams: filter/map/collect, laziness, groupingBy, and why a stream cannot be reused. */
|
||||
public class StreamsDemo {
|
||||
|
||||
public static void main(String[] args) {
|
||||
List<String> words = Arrays.asList("stream", "lambda", "optional", "default", "time", "stream");
|
||||
|
||||
System.out.println("distinct+upper : " + words.stream().distinct().map(String::toUpperCase).collect(Collectors.toList()));
|
||||
System.out.println("sum of lengths : " + words.stream().mapToInt(String::length).sum());
|
||||
|
||||
// laziness: nothing runs until the terminal operation
|
||||
Stream<String> lazy = words.stream().filter(w -> { System.out.println(" filtering " + w); return w.length() > 5; });
|
||||
System.out.println("pipeline built, nothing printed yet");
|
||||
System.out.println("first match : " + lazy.findFirst().get());
|
||||
|
||||
// reuse is an error
|
||||
Stream<String> once = words.stream();
|
||||
once.count();
|
||||
try { once.count(); } catch (IllegalStateException e) { System.out.println("reuse : " + e.getMessage()); }
|
||||
|
||||
Map<String, List<String>> byLen = words.stream().distinct().collect(Collectors.groupingBy(w -> w.length() > 5 ? "long" : "short"));
|
||||
System.out.println("groupingBy : " + new TreeMap<>(byLen));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import java.time.*;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
/** java.time: immutable value types, zones, Period vs Duration, and the old Date month trap. */
|
||||
public class TimeDemo {
|
||||
public static void main(String[] args) {
|
||||
LocalDate d = LocalDate.of(2026, 10, 20);
|
||||
System.out.println("plusMonths : " + d.plusMonths(1) + " (original still " + d + ")");
|
||||
System.out.println("end of month : " + LocalDate.of(2026, 1, 31).plusMonths(1));
|
||||
System.out.println("days between : " + ChronoUnit.DAYS.between(LocalDate.of(2026, 1, 1), d));
|
||||
System.out.println("Period : " + Period.between(LocalDate.of(2020, 2, 29), d));
|
||||
System.out.println("Duration : " + Duration.ofMinutes(135));
|
||||
ZonedDateTime mumbai = ZonedDateTime.of(2026, 10, 20, 22, 35, 0, 0, ZoneId.of("Asia/Kolkata"));
|
||||
System.out.println("same instant NY : " + mumbai.withZoneSameInstant(ZoneId.of("America/New_York")).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm z")));
|
||||
System.out.println("old Date month : new java.util.Date(126, 9, 20) -> month index " + new java.util.Date(126, 9, 20).getMonth() + " (October is 9)");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user