codestory

Syntax und neue Funktionen in Java 8

  1. Die Vorstellung
  2. Die standardmäßige Methode für die Interface
  3. Functional Interface (funktionsinterface)
  4. Die Ausdruck Lambda
  5. Functional Interface API
  6. Method reference

1. Die Vorstellung

Ab der Entstehung von Java und der Verbesserung der Syntax gibt es einige wichtigen Ereignisse
  • Java 1.0: Begin einer Programmierungssprache.
  • Java 1.1, 1.2, 1.3, 1.4 Es gibt keine große Änderung von der Syntax und Funktion.
  • Java 1.5 (oder Java genannt) hat die große Änderung mit der Einführung einiger Begriffen
    • Generic
    • Autoboxing/Unboxing
    • Verbesserung der Funktion für die Schleife for ("foreach").
    • ype-safe enumerations.
    • Varargs
    • Static import
    • Metadata
  • Java 6,7 hat keine große Änderung von der Sprache.
  • Java 8 hat eine große Änderung von der Sprache. Und es gibt einige neuen Begriffen und Funktion:
    • Default interface methods
    • Lambda expressions
    • Method references
    • Repeatable annotations
    • Stream
Im Unterlagen stelle ich die Funktion und die Syntax von Java 8 vor

2. Die standardmäßige Methode für die Interface

Java 8 erlaubt Sie, ein nicht-abstrakte Methode in die Interface durch das Schlusselwort default einzufügen. die Methode werden als die verlängerten Methode verstanden. Das ist Ihr erstes Beispiel
Formula.java
package org.o7planning.tutorial.j8.itf;

public interface Formula {

	// Eine abstrakte Methode erklären.
	double calculate(int a);

	// Eine nichtabstrakte Methode erklären.
	// Das Schlüsselwort default benutzen.
	// (Die Funtion zur Quadratwurzel einer Zahl).
	default double sqrt(int a) {
		return Math.sqrt(a);
	}

}
Und class FormulaImpl implementiert interface Formula.
FormulaImpl.java
package org.o7planning.tutorial.j8.itf;

// Eine Klasse implementiert die Formula Interface.
public class FormulaImpl implements Formula {

	// Nur die abstrakte Methode vom Formula durchführen
	@Override
	public double calculate(int a) {
		return a * a - a;
	}

}
FormulaTest.java
package org.o7planning.tutorial.j8.itf;

public class FormulaTest {

   public static void main(String[] args) {
       Formula formula = new FormulaImpl();

       // ==> 5
       double value1 = formula.sqrt(25);
       System.out.println("Value1 = " + value1);

       // ==> 600
       double value2 = formula.calculate(25);
       System.out.println("Value2 = " + value2);

   }

}

3. Functional Interface (funktionsinterface)

Java 8: in alle Interface gibt es eine einzige Abstraktmethod. Das ist Functional Interface. Sie können die annotation @FunctionalInterface verwenden um eine Interface von Ihnen als Functional Interface zu markieren. Das ist nicht obligatorisch, aber der Compiler von Java warnt einen Fehler für Sie wenn Sie unabsichtlich eine andere Abtraktsmethod in eine von dieser Annotation markierten Interface hinzufügen
Unten sind einige Beispiel mit @FunctionalInterface:
Das unten Beispiel ist eine gültige FunctionalInterface weil sie eine einzige Abstraktsmethod hat
Foo.java
package org.o7planning.tutorial.j8.funcitf;

@FunctionalInterface
public interface Foo {

  void something();

  default void defaultMethod() {
      System.out.println("..");
  }
}
Nicht gültig
Gültig:
Nicht gültig
Gültig:

4. Die Ausdruck Lambda

Zuerst sehen wir wieder wie die Java Version vor 8 eine vorhandene Collection ordnet.
SortBefore8Example.java
package org.o7planning.tutorial.j8.lambda;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class SortBefore8Example {

	public static void main(String[] args) {

		// Eine Liste der Früchte
		List<String> fruits = Arrays.asList("Grapefruit", "Apple", "Durian", "Cherry");

		// Die Utility-Methode von Collections benutzen um die Liste anzuordnen. 
		// Einen Vergleicher sorgen
		Collections.sort(fruits, new Comparator<String>() {

			@Override
			public int compare(String o1, String o2) {
				return o1.compareTo(o2);
			}

		});

		for (String fruit : fruits) {
			System.out.println(fruit);
		}

	}
}
Das Ergebnis von dem obengenannten Beispiel:
Apple
Cherry
Durian
Grapefruit
Java 8: Nur eine einzige Method in interface ist die Funktional Interface. Und bei der Implementierung dieser Interface brauchen Sie nur eine Method für die Durchführung der einzigen Abstraktsmethod. Comparator ist eine Interface, die eine einzige Interface hat. Und sie ist eine Functional Interface. Sie können das oben Beispiel mit der Syntax Lambda von Java 8 wieder schreiben
SortJava8Example.java
package org.o7planning.tutorial.j8.lambda;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class SortJava8Example {

	public static void main(String[] args) {

		// Eine Liste der Früchte.
		List<String> fruits = Arrays.asList("Grapefruit", "Apple", "Durian", "Cherry");

		// Die Utility-Methode von Collections um die Liste anzuordnen. 
		// Einen Vergleicher (Comparator) sorgen für den 2.parameter der Methode. 
		// Denn ein Comparator ist die einzige Interface mit der Methode.
		// ==> mit der Ausdruck Lambda kurz schreiben.
		// den Name der Interface schreiben nicht brauchen,
		// den Name der Methode schreiben nicht brauchen
		Collections.sort(fruits, (String o1, String o2) -> {
			return o1.compareTo(o2);
		});

		for (String fruit : fruits) {
			System.out.println(fruit);
		}

	}
}
Wenn es nur in einer Befehlsblock einen einzigen Befehl gibt, können Sie { } löschen. Dann Ihre Code kann kürzer sein
Collections.sort(fruits, (String o1, String o2) -> o1.compareTo(o2)  );
Sogar ist der Compiler von Java klug genug, um welche angemessene Anordnungstype der Elemente von Ihrer Collection zu kennen, in diesem Beispiel ist das String type. Und so ist der Comparator sicher der Vergleich von den Datentype String. Sie können Ihre Code kürzer schreiben
Collections.sort(fruits, (o1, o2) -> o1.compareTo(o2));
Ein anderes Beispiel mit dem Ausdruck Lambda
Converter.java
package org.o7planning.tutorial.j8.lambda;

@FunctionalInterface
public interface Converter<F, T> {
   
   T convert(F from);
   
}
Die Interface Converter nach dem Weg von Java vor der Version 8 benutzen (Keinen Ausdruck Lambda benutzen).
ConverterBefore8Example.java
package org.o7planning.tutorial.j8.lambda;

public class ConverterBefore8Example {

	public static void main(String[] args) {

		// Ein Objek Converter initializieren
		Converter<String, Integer> converter = new Converter<String, Integer>() {

			@Override
			public Integer convert(String from) {
				return Integer.parseInt(from);
			}

		};

		// ==> 100
		Integer value = converter.convert("0100");

		System.out.println("Value = " + value);
	}
}
Den Ausdruck Lambda von Java 8 benutzen
ConveterJava8Example.java
package org.o7planning.tutorial.j8.lambda;

public class ConveterJava8Example {

	public static void main(String[] args) {

		// Converter ist eine FunctionalInterface
		// Die Syntax vom Java 8 (Lambda) benutzen
		// In dem Fall: das Objekt aus FunctionalInterface direkt erstellen
		Converter<String, Integer> converter1 = (String from) -> {
			return Integer.parseInt(from);
		};

		// ==> 100
		Integer value1 = converter1.convert("0100");

		System.out.println("Value1 = " + value1);

		// Oder mehr einfach:
		Converter<String, Integer> converter2 = (from) -> Integer
				.parseInt(from);

		// ==> 200
		Integer value2 = converter2.convert("00200");

		System.out.println("Value2 = " + value2);
		
		// Wenn die Methode einen Parameter hat, können ignorieren ().
		Converter<String, Integer> converter3 = from -> Integer
				.parseInt(from);

		// ==> 300
		Integer value3 = converter3.convert("00300");

		System.out.println("Value3 = " + value3);
		
	}

}

5. Functional Interface API

Java 8 baut bereit eine große Menge von Functional Interface, die in der Package java.util.function liegen. Hier leite ich Sie bei der Verwendung einiger Interface um die Ausdruck Lambda und Ihren Nutzen zu verstehen
java.util.function.Consumer
Consumer ist eine Functional interface, die im Java 8 vorhanden sein. Sie hat eine einzige Abstraktmethod, die einen Input Parameter akzeptiert. Und diese method schickt nichts rück
Consumer.java
package java.util.function;

import java.util.Objects;

@FunctionalInterface
public interface Consumer<T> {
	
	// Die Methode akzeptiert einen Inputparameter und gibt nicht zurück
	void accept(T t);

}
Die method List.forEach(Consumer) benutzen
// java.util.List extends java.util.Collection  (extends Iterable)

// Interface java.util.Iterable:
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
   for (T t : this) {
       action.accept(t);
   }
}
ConsumerExample.java
package org.o7planning.tutorial.j8.api;

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class ConsumerExample {

	// Die Methode List.forEach(Consumer) mit der Syntax vom Java < 8 benutzen. 
	// Die Elemente von der Liste ausdrucken
	public static void beforeJ8() {
		List<String> list = Arrays.asList("a", "b", "c", "a1", "a2");

		list.forEach(new Consumer<String>() {

			@Override
			public void accept(String t) {
				System.out.println(t);
			}

		});
	}

	// Die Methode List.forEach(Consumer) mit der Syntax vom Java 8 benutzen 
	// (Die Lambda Ausdruck benutzen)
	public static void java8Consumer() {
		List<String> list = Arrays.asList("a", "b", "c", "a1", "a2");

		list.forEach((String t) -> {
			System.out.println(t);
		});
	}

	// Die Methode List.forEach(Consumer) nach der Syntax vom Java 8.
	// (Die Lambda Ausdruck benutzen)
	// mehr einfach
	public static void java8ConsumerMoreSimple() {
		List<String> list = Arrays.asList("a", "b", "c", "a1", "a2");

		list.forEach((String t) -> System.out.println(t));
	}
	
}
java.util.function.Predicate
Predicate ist eine im java 8 vorhandene Functional interface . sie hat eine einzige Abstraktsmethod mit der Akzeptierung eines Inputparameter und die Method schickt die Wert boolean (true/ false) rück. Diese Method bewertet, ob der Inputparameter eine Logic entspricht oder nicht.
Predicate.java
package java.util.function;

import java.util.Objects;

@FunctionalInterface
public interface Predicate<T> {

	// Einen Inputparameter bewerten und true oder false zurückgeben
	boolean test(T t);

}
Das Beispiel unten filtert ein Liste der natürlicher Zahl und druck die Liste von der ungeraden Zahl. Benutzen wir Predicate nach dem Weg von Java 8 und der Version vor Java 8
PredicateExample.java
package org.o7planning.tutorial.j8.api;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class PredicateExample {

	// Die Methode Stream.filter(Predicate<T>) nach dem Syntax vom Java < 8 benutzen. 
	// Eine Liste der Integerzahlen filtern und die ungeraden Zahlen ausdrucken
	public static void beforeJ8() {
		List<Integer> list = Arrays.asList(1, 4, 5, 1, 7, 8);

		// Ein Stream enthaltet die Elemente der oben Liste
		Stream<Integer> stream = list.stream();

		// Ein neues Stream enthaltet nur die ungeraden Zahlen.
		Stream<Integer> stream2 = stream.filter(new Predicate<Integer>() {

			@Override
			public boolean test(Integer t) {
				return t % 2 == 1;
			}
		});
	}

	// Die Methode Stream.filter(Predicate<T>) nach dem Syntax vom Java >= 8 benutzen. 
	// Eine Liste der Integerzahlen filtern und die ungeraden Zahlen ausdrucken
	// (Die Lambda Ausdruck benutzen).
	public static void java8Predicate() {
		List<Integer> list = Arrays.asList(1, 4, 5, 1, 7, 8);

		// Ein Stream enthaltet die Elemente der oben Liste
		Stream<Integer> stream = list.stream();

		// Ein neues Stream enthaltet nur die ungeraden Zahlen.
		Stream<Integer> stream2 = stream.filter(t -> {
			return t % 2 == 1;
		});

		// Stream.forEach(Consumer<T>)
		stream2.forEach(t -> System.out.println(t));
	}

	// kurzer und mehr einfach sein
	public static void java8ConsumerMoreSimple() {
		List<Integer> list = Arrays.asList(1, 4, 5, 1, 7, 8);

		// Ein Stream enthaltet die Elemente der oben Liste
		Stream<Integer> stream = list.stream();

		stream.filter(t -> t % 2 == 1).forEach(t -> System.out.println(t));
	}

}
java.util.function.Function
Function ist eine im Java 8 vorhandene Functional interface . sie hat eine einzige Abstraktsmethod mit der Akzeptierung eines Inputparameter und die Method schickt einen anderen Objekt rück
Function.java
package java.util.function;

import java.util.Objects;


@FunctionalInterface
public interface Function<T, R> {

	// Die Methode akzeptiert einen Parameter und eine Wert zurückgeben
	R apply(T t);

}
Beispiel: Eine Liste von String und Druck der String liste in einer Collection unter der Großbuchstabe Format
FunctionExample.java
package org.o7planning.tutorial.j8.api;

import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Stream;

public class FunctionExample {

	// Die Methode  Stream.map(Function) mit der Syntax vom Java < 8.
	// Die Liste der Elemente ausdrucken.
	public static void beforeJ8() {
		List<String> list = Arrays.asList("a", "c", "B", "e", "g");

		// Stream enthaltet die Elemente der Liste.
		Stream<String> stream = list.stream();

		// Stream.map(Function):
		// <R> Stream<R> map(Function<? super T, ? extends R> mapper);
		// Ein neues Stream mit den geänderten Elemente zurückgeben.
		Stream<String> streamUpper = stream.map(new Function<String, String>() {

			@Override
			public String apply(String t) {
				return t == null ? null : t.toUpperCase();
			}

		});

		streamUpper.forEach(t -> System.out.println(t));
	}

	public static void java8Function() {
		List<String> list = Arrays.asList("a", "c", "B", "e", "g");

		// Ein Stream enthaltet die Elemente der Liste
		Stream<String> stream = list.stream();

		stream.map(t -> t == null ? null : t.toUpperCase()).forEach(t -> System.out.println(t));
	}

	public static void main(String[] args) {

		beforeJ8();

		java8Function();
	}

}
Einige ähnlichen Funktional Interface
  • java.util.function.IntFunction<R>
  • java.util.function.DoubleFunction<R>
  • java.util.function.LongFunction<R>
@FunctionalInterface
public interface IntFunction<R> {
 
    R apply(int value);
}


@FunctionalInterface
public interface LongFunction<R> {
 
    R apply(long value);
}


@FunctionalInterface
public interface DoubleFunction<R> {
 
    R apply(double value);
}
java.util.function.Supplier
Supplier ist eine im Java 8 vorhandene Functional interface. Sie hat eine einzige Abstraktsmethod ohne den Parameter und die Method schickt einen Objekt rück
Supplier.java
package java.util.function;

@FunctionalInterface
public interface Supplier<T> {

	// Die Methode hat keinen Parameter aber gibt eine Wert zurück
	T get();

}
SupplierExample.java
package org.o7planning.tutorial.j8.api;

import java.util.function.Supplier;

public class SupplierExample {

	// Eine Methode mit dem Parameter  Supplier<String>.
	public static void display(Supplier<String> supp) {
		System.out.println(supp.get());
	}

	// Die Ausdruck Lambda nicht benutzen.
	public static void beforeJ8() {
		display(new Supplier<String>() {

			@Override
			public String get() {
				return "Hello";
			}
		});
		display(new Supplier<String>() {

			@Override
			public String get() {
				return "World";
			}
		});
	}

	// Die Ausdruck Lambda  benutzen..
	public static void java8Supplier() {
		display(() -> {
			return "Hello";
		});

		display(() -> {
			return "World";
		});
	}

	// Die Ausdruck Lambda  benutzen.
	// (kürzer).
	public static void java8SupplierShortest() {
		display(() -> "Hello");

		display(() -> "World");
	}

	public static void main(String[] args) {

		beforeJ8();
		System.out.println("-----------");
		java8SupplierShortest();
	}

}
Einige beziehungweisen Functional Interface
  • java.util.function.BooleanSupplier
  • java.util.function.IntSupplier
  • java.util.function.DoubleSupplier
  • java.util.function.LongSupplier

6. Method reference

Das ist eine Funktion über den Ausdruck Lambda. Es ermöglicht Ihnen, eine Method oder eine Constructor ohne die Durchführung zu verweisen. Method References und Lambda sind ziemlich ähnlich denn die beide fordern eine angemessene Functional Interface
Java 8 ermöglicht Ihnen, eine Referenz von einer Method oder einen Constructor durch die Benutzung eines Schlüsselswort zu geben:
Zuerst sehen Sie ein einfaches Beispiel
MyFunction ist eine Functional Interface. Sie definiert eine Method mit 2 Parameter int a und b, und schickt die Wert int rück.
MyFunction.java
package org.o7planning.tutorial.j8.mref;

@FunctionalInterface
public interface MyFunction {

	// Die Methode hat 2 Parameter a, b und gibt das int Typ zurück
	public int doSomething(int a, int b);

}
MyMathUtils ist eine Class mit 2 static Method um die Summe und Differenz der 2 Zahl int zu kalkulieren
MyMathUtils.java
package org.o7planning.tutorial.j8.mref;

public class MyMathUtils {

	// Die Methode hat 2 Parameter a, b und gibt das Int Typ zurück.
	// Die Methode hat den unterschiedlichen Namen aber 
	// die gleichen Struktur mit  MyFunction.doSomething(int,int).
	public static int sum(int a, int b) {
		return a + b;
	}

	public static int minus(int a, int b) {
		return a - b;
	}

}
MethodReferenceExample.java
package org.o7planning.tutorial.j8.mref;

public class MethodReferenceExample {

	// Der 3.Parameter von der Methode ist MyFunction (Functional Interface).
	// Bei der Benutzung von der Methode:
	// Sie können die Referenz einer Methode für den 3. Parameter übertragen 
	// (Die Methode hat den gleichen Typ mit MyFunction).
	public static int action(int a, int b, MyFunction func) {
		return func.doSomething(a, b);
	}

	public static void main(String[] args) {
		int a = 100;
		int b = 30;

		// Die Referenz der Ausdruck MyMathUtils.sum. zuweisen
		int c = action(a, b, MyMathUtils::sum);// ==> 130.

		System.out.println("c = " + c);

		// Die Referenz der Ausdruck  MyMathUtils.minus.übertragen
		int d = action(a, b, MyMathUtils::minus);// ==> 70

		System.out.println("d = " + d);

		// Die Referenz der Ausdruck  Math.subtractExact übertragen
		int e = action(a, b, Math::subtractExact);// ==> 70

		System.out.println("e = " + e);

		// Die Referenz der Ausdruck  Math.min übertragen
		// Pass the reference of Math.min method.
		int f = action(a, b, Math::min);// ==> 30

		System.out.println("f = " + f);
	}
}
Durch das oben Beispiel können Sie kenne, wie das Schlusselwort :: benutzt wird um die Referenz der Methode überzutragen. Wenn Sie eine Methode aufrufen und in dieser Methode gibt es einen Parameter als Functional Interface, können Sie dann eine Referenz übertragen, deren Struktur so gleich wie die Struktur von der Functional interface definierten Methode.

Java Grundlagen

Show More