Die größte Neuerung auf der Sprachseite von Java 8 sind Lambda-Ausdrücke. In Java 8 können in Interfaces auch nicht-abstrakte Methoden haben. Weiter wurden das funktionale Interface eingeführt.
package de.snowbits.j8;
public class ABImpl implements A, B {
@Override
public void doSomething() {
System.out.println("ABImpl");
A.super.doSomething(); // A.super syntax
B.super.doSomething(); // B.super syntax
}
public static void main(String[] args) {
ABImpl testImpl = new ABImpl();
testImpl.doSomething();
// ABCImpl
// A
// B
}
}
package de.snowbits.j8;
public interface A {
default void doSomething() {
System.out.println("A");
}
}
package de.snowbits.j8;
public interface B {
default void doSomething() {
System.out.println("B");
}
}
package de.snowbits.j8;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.OptionalDouble;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import de.snowbits.j8.Person.Sex;
public class Java8Examples {
public static Function<Integer, Integer> square = (x) -> x * x;
public static BiFunction<Integer, Integer, Integer> squareAdd = (x, y) -> x * x + y * y;
public static void main(String[] args) {
int testStep = 1;
debugNextStageWithLineSeperator(testStep++);
System.out.println(square.apply(5));
System.out.println(squareAdd.apply(5, 10));
// 25
// 125
debugNextStageWithLineSeperator(testStep++);
int c = 3; // wird zur Konstante und ist nicht mehr änderbar.
Function<Double, Double> function = a -> a * a / c;
System.out.println(function.apply(9d));
// 27.0
debugNextStageWithLineSeperator(testStep++);
Function<String, Function<String,String>> factory = name -> (sort -> name + " \t= " + sort);
Function<String, String> fruit = factory.apply( "Obst");
Function<String, String> vegetable = factory.apply( "Gemüse");
System.out.println(fruit.apply("Apfel"));
System.out.println(fruit.apply("Birne"));
System.out.println(vegetable.apply( "Gurke"));
System.out.println(vegetable.apply( "Kohl"));
// Obst = Apfel
// Obst = Birne
// Gemüse = Gurke
// Gemüse = Kohl
debugNextStageWithLineSeperator(testStep++);
List<Person> persons = Arrays.asList(new Person[] {
new Person(Sex.MALE, "Max", "Muster", 25),
new Person(Sex.FEMALE, "Maxi", "Muster", 22),
new Person(Sex.MALE, "Mäxchen", "Muster", 4)});
persons.forEach(System.out::println);
// [sex: MALE; firstname: Max; lastname: Muster; age: 25]
// [sex: FEMALE; firstname: Maxi; lastname: Muster; age: 22]
// [sex: MALE; firstname: Mäxchen; lastname: Muster; age: 4]
debugNextStageWithLineSeperator(testStep++);
persons.forEach(person -> System.out.println(person));
// [sex: MALE; firstname: Max; lastname: Muster; age: 25]
// [sex: FEMALE; firstname: Maxi; lastname: Muster; age: 22]
// [sex: MALE; firstname: Mäxchen; lastname: Muster; age: 4]
debugNextStageWithLineSeperator(testStep++);
persons.stream().filter(person -> person.getAge() <= 18).forEach(System.out::println);
// [sex: MALE; firstname: Mäxchen; lastname: Muster; age: 4]
debugNextStageWithLineSeperator(testStep++);
persons.stream().filter(person -> person.getAge() >= 18 && person.getSex() == Sex.FEMALE)
.forEach(person -> printPerson(person));
// [sex: FEMALE; firstname: Maxi; lastname: Muster; age: 22]
debugNextStageWithLineSeperator(testStep++);
Integer totalAge = persons.stream().mapToInt(Person::getAge).sum();
Integer maxAge = persons.stream().mapToInt(Person::getAge).max().getAsInt();
Integer minAge = persons.stream().mapToInt(Person::getAge).min().getAsInt();
Integer averageAge = (int) persons.stream().mapToInt(Person::getAge).average().getAsDouble();
System.out.println("totalAge: " + totalAge);
System.out.println("maxAge: " + maxAge);
System.out.println("minAge: " + minAge);
System.out.println("averageAge: " + averageAge);
// totalAge: 51
// maxAge: 25
// minAge: 4
// averageAge: 17
debugNextStageWithLineSeperator(testStep++);
persons.stream().mapToInt(Person::getAge).sorted().forEach(System.out::println);
// 4
// 22
// 25
debugNextStageWithLineSeperator(testStep++);
persons.stream()
.sorted((person1, person2) -> Integer.compare(person1.getAge(), person2.getAge()))
.forEach(person -> System.out.println(person));
// [sex: MALE; firstname: Mäxchen; lastname: Muster; age: 4]
// [sex: FEMALE; firstname: Maxi; lastname: Muster; age: 22]
// [sex: MALE; firstname: Max; lastname: Muster; age: 25]
debugNextStageWithLineSeperator(testStep++);
List<String> myList = new ArrayList<String>();
myList.addAll(Arrays.asList(new String[] { "abc", "", " def ", null, " ", "ghi" }));
myList.removeIf( s -> s == null );
myList.replaceAll( String::trim );
myList.removeIf( String::isEmpty );
myList.forEach( System.out::println );
// abc
// def
// ghi
debugNextStageWithLineSeperator(testStep++);
Stream.of(1, 2, 3, 4).forEach( (x) -> {
System. out. println("forEach: " + x);
}) ;
// forEach: 1
// forEach: 2
// forEach: 3
// forEach: 4
debugNextStageWithLineSeperator(testStep++);
Map<Boolean, List<Integer>> even = Stream.of(1, 2, 3, 4).collect(
Collectors. groupingBy( i -> i % 2 == 0) );
System.out.print(even);
// {false=[1, 3], true=[2, 4]}
}
public static void printPerson(Person person) {
System.out.println(person);
}
private static void debugNextStageWithLineSeperator(int number) {
System.out.println("\n------------------------------------------");
System.out.println("Test " + number + ":");
System.out.println("------------------------------------------");
}
}
package de.snowbits.j8;
public class Person {
public enum Sex {
MALE, FEMALE
}
private Sex _sex;
private String _firstname;
private String _lastname;
private int _age;
public Person(Sex sex, String firstname, String lastname, int age) {
_sex = sex;
_firstname = firstname;
_lastname = lastname;
_age = age;
}
public Sex getSex() {
return _sex;
}
public String getFirstname() {
return _firstname;
}
public String getLastname() {
return _lastname;
}
public int getAge() {
return _age;
}
@Override
public String toString() {
return new StringBuilder()
.append("[sex: ").append(getSex())
.append("; firstname: ").append(getFirstname())
.append("; lastname: ").append(getLastname())
.append("; age: ").append(getAge())
.append("]")
.toString();
}
}
package de.snowbits.j8;
public class Calculator {
public static final DoubleMath addition = (a, b) -> a + b;
public static final DoubleMath subtraction = (a, b) -> a - b;
public static final DoubleMath multiplication = (a, b) -> a * b;
public static final DoubleMath division = (a, b) -> a / b;
public static void main(String[] args) {
Calculator calc = new Calculator();
double x = 50d;
double y = 25d;
System.out.println(x + " + " + y + " = " + calc.operate(addition, x, y));
System.out.println(x + " - " + y + " = " + calc.operate(subtraction, x, y));
System.out.println(x + " * " + y + " = " + calc.operate(multiplication, x, y));
System.out.println(x + " : " + y + " = " + calc.operate(division, x, y));
// 50.0 + 25.0 = 75.0
// 50.0 - 25.0 = 25.0
// 50.0 * 25.0 = 1250.0
// 50.0 : 25.0 = 2.0
}
public double operate(DoubleMath doubleMath, double a, double b) {
return doubleMath.operation(a, b);
}
public interface DoubleMath {
double operation(double a, double b);
}
}
Syntax | Regel | |
---|---|---|
Parameterlisten | ||
(int x) -> x + 1 | Parameterliste mit einem Parameter und expliziter Typangabe | |
falsch | int x -> x + 1 | Parameterliste mit Typangabe stets in Klammern |
(x) -> x + 1 | Parameterliste mit einem Parameter ohne explizite Typangabe | |
x -> x + 1 | Parameterliste mit einem Parameter ohne explizite Typangabe: Klammern dürfen weggelassen werden | |
(int x, short y) -> x + y | Parameterliste mit zwei Parametern und expliziten Typangaben | |
falsch | int x, short y -> x + y | Parameterliste mit Typangaben stets in Klammern |
(x, y) -> x + y | Parameterliste mit zwei Parametern ohne explizite Typangaben | |
falsch | (x, short y) -> x + y | keine Mischung von Parametern mit und ohne explizite Typangabe |
() -> 42 | Parameterliste darf leer sein | |
Funktionenrümpfe | ||
(x,y) -> x * x - y * y | Rumpf mit nur einem Ausdruck | |
x -> { . . Anweisungen; . . . return wert; } |
Rumpf als Block mit mehreren Anweisungen und abschließender return-Anweisung | |
falsch | (int x) -> return x + 1 | die return-Anweisung nur innerhalb eines Blocks mit geschweiften Klammern { ... } |
Interface | Lambda-Ausdruck | Auswertungsmethode | Bemerkung |
---|---|---|---|
Consumer<T> | (T x) -> const; | accept(T x) | ein Parameter, keine Rückgabe |
Supplier<T> | () -> const; | get() | kein Parameter, Rückgabe vom Typ T |
Predicate<T> | x -> x < 5; | test(T x) | ein Parameter vom Typ T, Rückgabe vom Typ boolean |
Function<T,R> | x -> x * x - x + 1; | apply(T x) | ein Parameter vom Typ T, Rückgabe vom Typ R |
BiFunction<T,U,R> | (x,y) -> x * x - y * y; | apply(T x, U y) | zwei Parameter vom Typ T und U, Rückgabe vom Typ R |
package de.snowbits.j8;
import java.util.stream.IntStream;
public class Sample1 {
public static void main(String[] args) {
System.out.println("isPrime: " + isPrime(1));
System.out.println("isPrime: " + isPrime(2));
System.out.println("isPrime: " + isPrime(3));
System.out.println("isPrime: " + isPrime(4));
System.out.println("--- ");
System.out.println("isPrimeJava8: " + isPrimeJava8(1));
System.out.println("isPrimeJava8: " + isPrimeJava8(2));
System.out.println("isPrimeJava8: " + isPrimeJava8(3));
System.out.println("isPrimeJava8: " + isPrimeJava8(4));
}
private static boolean isPrime(final int number) {
for (int i = 2; i < number; i++) {
if (number % i == 0)
return false;
}
return number > 1;
}
private static boolean isPrimeJava8(final int number) {
return number > 1 && IntStream.range(2, number)
.noneMatch(index -> number % index == 0);
}
}
isPrime: false
isPrime: true
isPrime: true
isPrime: false
---
isPrimeJava8: false
isPrimeJava8: true
isPrimeJava8: true
isPrimeJava8: false
package de.snowbits.j8;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class Sample2 {
public static final boolean isGreaterThan3(int number) {
System.out.println("isGreaterThan3: " + number);
return number > 3;
}
public static final boolean isEven(int number) {
System.out.println("isEven: " + number);
return number > 3 && number % 2 == 0;
}
public static final int doubleIt(int number) {
System.out.println("doubleIt: " + number);
return number * 2;
}
public static void main(String[] args) {
// java
List<Integer> values = Arrays.asList(1, 2, 3, 5, 4, 6, 7, 8, 9, 10);
int result = 0;
for (Integer element : values) {
if (element > 3 && element % 2 == 0) {
result = element * 2;
break;
}
}
System.out.println("java: " + result);
System.out.println("--- ");
// java 8 Lösung 1
System.out.println("java 8 L-1: " +
values.stream()
.filter(e -> e > 3)
.filter(e -> e % 2 == 0)
.map(e -> e * 2)
.findFirst()
);
System.out.println("--- ");
// java 8 Lösung 2
final Stream<Integer> temp = values.stream()
.filter(Sample2::isGreaterThan3)
.filter(Sample2::isEven)
.map(Sample2::doubleIt);
System.out.println("java 8 L-2: " + temp.findFirst());
System.out.println("--- ");
// java 8 Lösung 3
Predicate<Integer> isGreaterThan3 = number -> number > 3;
Predicate<Integer> isEven = number -> number % 2 == 0;
Function<Integer, Integer> doubleIt = number -> number * 2;
final Stream<Integer> temp3 = values.stream()
.filter(isGreaterThan3)
.filter(isEven)
.map(doubleIt);
System.out.println("java 8 L-3: " + temp3.findFirst());
}
}
java: 8
---
java 8 L-1: Optional[8]
---
isGreaterThan3: 1
isGreaterThan3: 2
isGreaterThan3: 3
isGreaterThan3: 5
isEven: 5
isGreaterThan3: 4
isEven: 4
doubleIt: 4
java 8 L-2: Optional[8]
---
java 8 L-3: Optional[8]
package de.snowbits.j8;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
interface Selector {
boolean pick(int number);
}
public class Sample3 {
public static void main(String[] args) {
List<Integer> values = Arrays.asList(1, 2, 3, 5, 4, 6, 7, 8, 9, 10);
System.out.println("totalValues: " + totalValues(values));
System.out.println("totalValues selector: " + totalValues(values, e -> true));
System.out.println("totalValues selector even: " + totalValues(values, e -> e % 2 == 0));
System.out.println("totalValues2 selector even: " + totalValues2(values, e -> e % 2 == 0));
}
public static final int totalValues(List<Integer> numbers) {
int result = 0;
for (int element : numbers) {
result += element;
}
return result;
}
public static final int totalValues(List<Integer> numbers, Selector selector) {
int result = 0;
for (int element : numbers) {
if (selector.pick(element))
result += element;
}
return result;
}
public static final int totalValues2(List<Integer> numbers, Predicate<Integer> selector) {
return numbers.stream()
.filter(selector)
.reduce(0, Math::addExact);
}
}
totalValues: 55
totalValues selector: 55
totalValues selector even: 30
totalValues2 selector even: 30