java tutorial - Синтаксис и новые функции в Java 8 - учебник java - java programming - учиться java - java basics - java for beginners



1- Введение

  • С момента изобретения Java до обновления синтаксиса и функций, стоит отметить несколько важных этапов:
  • Java 1.0: Начало языка программирования.
  • Java 1.1, 1.2, 1.3, 1.4 не так много изменений в синтаксисе и функции.
  • Java 1.5 (Или Java 5) произошли большие изменения вместе с добавлением некоторых новых понятий.
    • Generic (Общий)
    • Autoboxing/Unboxing (Упаковка/распаковка)
    • Обновление функции цикла for ("foreach").
    • Виды перечисления. (Type-safe enumerations).
    • Varargs (Переменные аргументы)
    • Статический импорт (Static import)
    • Metadata (Метаданные)
  • Java 6,7 нет больших изменений в языке.
  • Java 8 произошло большое изменение в языке, наряду с добавлением некоторых новых понятий и функций:
    • Методы по умолчанию для интерфейса(Default interface methods)
    • Lambda выражения (Lambda expressions)
    • Справочные методы
    • Повторяющиеся аннотации (Repeatable annotations)
    • Поток (stream)
  • В этой статье я ознакомлю вас с функциями и синтаксисами Java 8.

2- Методы по умолчанию для интерфейса

  • Java 8 позволяет вам добавить невизуальный метод в интерфейс, используя ключевок слово default. Эти методы понимаются как расширенные методы. Это ваш первый пример:

Formula.java

package org.wikitechy.tutorial.j8.itf;
 
public interface Formula {
 
    // Объявить абстрактный метод.
    double calculate(int a);
 
    // Объявить неабстрактный метод.
    // Использовать ключевок слово default.
    // (Функция считает квадратный корень числа).
    default double sqrt(int a) {
        return Math.sqrt(a);
    }
 
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда
  • И класс FormulaImpl реализует interface Formula.

FormulaImpl.java

package org.wikitechy.tutorial.j8.itf;
 
// Класс выполняет interface Formula.
public class FormulaImpl implements Formula {
 
    // Нужно только выполнить абстрактный метод Formula.
    @Override
    public double calculate(int a) {
        return a * a - a;
    }
 
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда

FormulaTest.java

package org.wikitechy.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);
 
   }
 
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда

3- Functional Interface (Функциональный интерфейс)

  • Java8 считает, что интерфейсы имеют один абстрактный метод - это Functional Interface (функциональный интерфейс). Вы можете использовать аннотацию @FuctionalInterface, чтобы отметить ваш интерфейс как Функциональный интерфейс, это не обязательно. Однако компилятор (complier) Java уведомит вас об ошибке, если по нечаянно добавить другой абстрактный метод в интерфейс, отмеченный этой аннотацией.
  • Ниже являются некоторые практические примеры с @FunctionalInterface:
  • Приведенный ниже пример является действительным FunctionalInterface, потому что он имеет только один абстрактный метод.

Foo.java

package org.wikitechy.tutorial.j8.funcitf;
 
@FunctionalInterface
public interface Foo {
 
  void something();
 
  default void defaultMethod() {
      System.out.println("..");
  }
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда

Недействительно:

 функциональный интерфейс
java - джава - учиться java - учебник java -
функциональный интерфейс
- примеры java - java-программы

Действительно:

 компаратор
java - джава - учиться java - учебник java -
компаратор
- примеры java - java-программы

Недействительно:

 клон-java
java - джава - учиться java - учебник java -
клон-java
- примеры java - java-программы

Действительно:

 пакет java
java - джава - учиться java - учебник java -
пакет java
- примеры java - java-программы

4- Выражение Lambda

  • Сначала мы рассмотрим, как Java до версии 8 организует Collection.

SortBefore8Example.java

package org.wikitechy.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) {
 
        // Список фруктов.
        List<String> fruits = Arrays.asList("Grapefruit", "Apple", "Durian", "Cherry");
 
        // Использовать утилитарный метод Collections
        // чтобы перераспределить коллекцию.
        // Предоставить Comparator (Компаратор).
        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);
        }
 
    }
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда
  • Результат запуска примера выше:
 сортировать перед
java - джава - учиться java - учебник java -
сортировать перед
- примеры java - java-программы
  • Java 8 считает что интерфейсы, имеют только один метод, который является функциональным интерфейсом ( Functional Interface). Соответственно, при реализации интерфейса вам нужно всего лишь написать метод, реализующий этот единственный абстрактный метод. Comparator - это интерфейс, имеющий только один абстрактный метод, и это функциональный интерфейс ( Functional Interface). Вы можете переписать приведенный выше пример с синтаксисом Lambda Java 8:

SortJava8Example.java

package org.wikitechy.tutorial.j8.lambda;
 
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
 
public class SortJava8Example {
 
    public static void main(String[] args) {
 
        // Список фруктов.
        List<String> fruits = Arrays.asList("Grapefruit", "Apple", "Durian", "Cherry");
 
        // Использовать утилитарный метод Collections чтобы перераспределить список выше.
        // Предоставить Comparator (Компаратор) для второго параметра метода.
        // Так как Comparator это интерфейс с единственным методом.
        // ==> Можно сократить с выражением Lambda.
        // Не нужно писать название интерфейса,
        // Не нужно писать название метода.
        Collections.sort(fruits, (String o1, String o2) -> {
            return o1.compareTo(o2);
        });
 
        for (String fruit : fruits) {
            System.out.println(fruit);
        }
 
    }
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда
  • В блоке команд, если есть только одна команды, вы можете удалить { }, и вы можете написать этот раздел кода более кратким образом.
Collections.sort(fruits, (String o1, String o2) -> o1.compareTo(o2)  );
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда
  • Даже компилятор (compilier) Java достаточно умен, чтобы определить, какой вид элементов вам нужно организовать, в этом примере это вид String. Таким образом, компаратор ( Comparator), безусловно, означает сравнение видов данных String. Вы можете написать это более кратко.
Collections.sort(fruits, (o1, o2) -> o1.compareTo(o2));
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда

Другие примеры с выражением Lambda.

Converter.java

package org.wikitechy.tutorial.j8.lambda;
 
@FunctionalInterface
public interface Converter<F, T> {
    
   T convert(F from);
    
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда
  • Используйте интерфейс Converter в виде Java до версии 8 (это означает, что не используйте Lambda).

ConverterBefore8Example.java

package org.wikitechy.tutorial.j8.lambda;
 
public class ConverterBefore8Example {
 
    public static void main(String[] args) {
 
        // Инициализировать объект Converter.
        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);
    }
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда
  • Использование выражения Lambda на Java 8:

ConveterJava8Example.java

package org.wikitechy.tutorial.j8.lambda;
 
public class ConveterJava8Example {
 
    public static void main(String[] args) {
 
        // Converter (Конвертер) является FunctionalInterface
        // Использовать синтаксис в Java 8 (Lambda)
        // В случае: Создать объект напрямую из FunctionalInterface.
        Converter<String, Integer> converter1 = (String from) -> {
            return Integer.parseInt(from);
        };
 
        // ==> 100
        Integer value1 = converter1.convert("0100");
 
        System.out.println("Value1 = " + value1);
 
        // Или проще:
        Converter<String, Integer> converter2 = (from) -> Integer
                .parseInt(from);
 
        // ==> 200
        Integer value2 = converter2.convert("00200");
 
        System.out.println("Value2 = " + value2);
         
        // Если метод имеет только один параметр, можно пропустить ().
        Converter<String, Integer> converter3 = from -> Integer
                .parseInt(from);
 
        // ==> 300
        Integer value3 = converter3.convert("00300");
 
        System.out.println("Value3 = " + value3);
         
    }
 
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда

5- Functional Interface API

  • Java 8 имеет большое количество доступных разработанных Functional Interface, они находятся в пакете java.util.function, здесь я покажу вам как использовать некоторые из этих интерфейсов, чтобы лучше понять выражение Lambda и их полезность.

5.1- java.util.function.Consumer

  • Consumer (Потребитель) - это доступный функциональный интерфейс Java 8. Он имеет единственный абстрактный метод, принимающий входной параметр, и этот метод ничего не возвращает.

Consumer.java

package java.util.function;
 
import java.util.Objects;
 
@FunctionalInterface
public interface Consumer<T> {
     
    // Метод принимает один входной параметр и ничего не возвращает.
    void accept(T t);
 
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда
  • Использование метода List.forEach(Consumer):
// 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);
   }
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда

ConsumerExample.java

package org.wikitechy.tutorial.j8.api;
 
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
 
public class ConsumerExample {
 
    // Использовать метод List.forEach(Consumer) с синтаксисом в Java < 8.
    // Напечатать список элементов List.
    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);
            }
 
        });
    }
 
    // Использовать метод List.forEach(Consumer) с синтаксисом в Java 8.
    // Используя выражение Lambda.
    public static void java8Consumer() {
        List<String> list = Arrays.asList("a", "b", "c", "a1", "a2");
 
        list.forEach((String t) -> {
            System.out.println(t);
        });
    }
 
    // Использовать метод List.forEach(Consumer) с синтаксисом в Java 8.
    // Используя выражение  Lambda.
    // (Проще)
    public static void java8ConsumerMoreSimple() {
        List<String> list = Arrays.asList("a", "b", "c", "a1", "a2");
 
        list.forEach((String t) -> System.out.println(t));
    }
     
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда

5.2- java.util.function.Predicate

  • Predicate - это доступный функциональный интерфейс Java 8. Он имеет единственный абстрактный метод, принимающий входной параметр, и метод возвращает значение boolean (true / false). Этот метод используется для оценки того, подходит ли входной параметр для чего-то логического или нет.

Predicate.java

package java.util.function;
 
import java.util.Objects;
 
@FunctionalInterface
public interface Predicate<T> {
 
    // Оценивает входной параметр и возвращает true или false.
    boolean test(T t);
 
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда
  • В следующем примере мы будем фильтровать список целых нечетных чисел, используя Predicate, принимающий форму Java8 и предыдущих версий.

PredicateExample.java

package org.wikitechy.tutorial.j8.api;
 
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;
 
public class PredicateExample {
 
    // Использовать метод Stream.filter(Predicate<T>) по синтаксису в Java < 8.
    // Отфильтровать список целых чисел и напечатать нечетные числа.
    public static void beforeJ8() {
        List<Integer> list = Arrays.asList(1, 4, 5, 1, 7, 8);
 
        // Stream содержит элементы списка выше.
        Stream<Integer> stream = list.stream();
 
        // Новый Stream содержит только нечетные числа.
        Stream<Integer> stream2 = stream.filter(new Predicate<Integer>() {
 
            @Override
            public boolean test(Integer t) {
                return t % 2 == 1;
            }
        });
    }
 
    // Использовать метод Stream.filter(Predicate<T>) по синтаксису в  Java >= 8.
    // Отфильтровать список целых чисел и напечатать нечетные числа.
    // Используя выражение Lambda.
    public static void java8Predicate() {
        List<Integer> list = Arrays.asList(1, 4, 5, 1, 7, 8);
 
        // Stream содержит элементы списка выше.
        Stream<Integer> stream = list.stream();
 
        // Новый Stream содержит только нечетные числа.
        Stream<Integer> stream2 = stream.filter(t -> {
            return t % 2 == 1;
        });
 
        // Stream.forEach(Consumer<T>)
        stream2.forEach(t -> System.out.println(t));
    }
 
    // Еще проще и кратче.
    public static void java8ConsumerMoreSimple() {
        List<Integer> list = Arrays.asList(1, 4, 5, 1, 7, 8);
 
        // Stream содержит элементы списка выше.
        Stream<Integer> stream = list.stream();
 
        stream.filter(t -> t % 2 == 1).forEach(t -> System.out.println(t));
    }
 
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда

5.3- java.util.function.Function

  • Function - это доступный функциональный интерфейс Java 8. Он имеет единственный абстрактный метод, принимающий входной параметр, и метод возвращает другой объект.

Function.java

package java.util.function;
 
import java.util.Objects;
 
 
@FunctionalInterface
public interface Function<T, R> {
 
    // Этот метод принимает один параметр.
    // ​​​​​​​Возвращает одно значение
    R apply(T t);
 
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда
  • Пример: Дан список String, распечатайте String в списке с заглавными буквами

FunctionExample.java

package org.wikitechy.tutorial.j8.api;
 
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Stream;
 
public class FunctionExample {
 
    // Использовать метод Stream.map(Function) с синтаксисом в Java < 8.
    // Напечатать список элементов List.
    public static void beforeJ8() {
        List<String> list = Arrays.asList("a", "c", "B", "e", "g");
 
        // Stream содержит элементы списка.
        Stream<String> stream = list.stream();
 
        // Stream.map(Function):
        // <R> Stream<R> map(Function<? super T, ? extends R> mapper);
        // Возвращает новый Stream, с измененными элементами.
        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");
 
        // Stream содержит элементы списка.
        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();
    }
 
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда
  • Аналогичные функциональные интерфейсы (Functional interface):
    • java.util.function.IntFunction
    • java.util.function.DoubleFunction
    • java.util.function.LongFunction
@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 tutorials - команда

5.4- java.util.function.Supplier

  • Supplier - это доступный функциональный интерфейс Java 8. Он имеет единственный абстрактный метод без параметра, а метод возвращает объект.

Supplier.java

package java.util.function;
 
@FunctionalInterface
public interface Supplier<T> {
 
    // Этот метод не имеет параметров.
    // Но возвращает результат.
    T get();
 
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда

SupplierExample.java

package org.wikitechy.tutorial.j8.api;
 
import java.util.function.Supplier;
 
public class SupplierExample {
 
    // Метод с параметром Supplier<String>.
    public static void display(Supplier<String> supp) {
        System.out.println(supp.get());
    }
 
    // Не используя выражение Lambda.
    public static void beforeJ8() {
        display(new Supplier<String>() {
 
            @Override
            public String get() {
                return "Hello";
            }
        });
        display(new Supplier<String>() {
 
            @Override
            public String get() {
                return "World";
            }
        });
    }
 
    // Используя выражение Lambda.
    public static void java8Supplier() {
        display(() -> {
            return "Hello";
        });
 
        display(() -> {
            return "World";
        });
    }
 
    // Используя выражение Lambda.
    // (Еще кратче).
    public static void java8SupplierShortest() {
        display(() -> "Hello");
 
        display(() -> "World");
    }
 
    public static void main(String[] args) {
 
        beforeJ8();
        System.out.println("-----------");
        java8SupplierShortest();
    }
 
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда
  • Аналогичные функциональные интерфейсы (Functional interface):
    • java.util.function.BooleanSupplier
    • java.util.function.IntSupplier
    • java.util.function.DoubleSupplier
    • java.util.function.LongSupplier

6- Method reference

  • Это функция, связанная с выражением Lambda. Она позволяет вам ссылаться на другие конструкторы или методы, не выполняя их. Ссылки на методы (method references) и Lambda аналогичны тем, что они оба требуют один вид цели, это совместимый функциональный интерфейс.
  • Java 8 позволяет передавать ссылку метода или конструктора с помощью ключевого слова ::
  • Прежде чем смотреть на детали, давайте посмотрим простой пример.
  • MyFunction - это функциональный интерфейс. Он определяет метод, который имеет два параметра: int a и b и возвращает значение int.

MyFunction.java

package org.wikitechy.tutorial.j8.mref;
 
@FunctionalInterface
public interface MyFunction {
 
    // Этот метод имеет 2 параметра a, b и возвращает вид int.
    public int doSomething(int a, int b);
 
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда
  • MyMathUtils - это класс с двумя статическими методами, используемыми для вычисления суммы и разность двух чисел int

MyMathUtils.java

package org.wikitechy.tutorial.j8.mref;
 
public class MyMathUtils {
 
    // Этот метод имеет 2 параметра a, b и возвращает вид int.
    // Этот метод имеет другое название,
    // но структура похожа на 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;
    }
 
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда

MethodReferenceExample.java

package org.wikitechy.tutorial.j8.mref;
 
public class MethodReferenceExample {
 
    // Третий параметр данного метода является MyFunction (Functional Interface).
    // При использовании данного метода:
    // Вы можете передать ссылку метода для третьего параметра.
    // (Методы должны быть одного вида с 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;
 
        // Передать ссылку метода MyMathUtils.sum.
        int c = action(a, b, MyMathUtils::sum);// ==> 130.
 
        System.out.println("c = " + c);
 
        // Передать ссылку метода MyMathUtils.minus.
        int d = action(a, b, MyMathUtils::minus);// ==> 70
 
        System.out.println("d = " + d);
 
        // Передать ссылку метода Math.subtractExact.
        int e = action(a, b, Math::subtractExact);// ==> 70
 
        System.out.println("e = " + e);
 
        // Передать ссылку метода Math.min.
        int f = action(a, b, Math::min);// ==> 30
 
        System.out.println("f = " + f);
    }
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда
  • По примеру выше, вы можете увидеть способ использования ключевого слова :: чтобы передать ссылку метода. Если вы вызываете метод, а в том методе имеется аргумент Functional Interface, вы можете передать метод ссылки со структурой похожей на структуру метода определения в Functional interface.

Related Searches to Синтаксис и новые функции в Java 8