Рубрики
Без рубрики

Учебное пособие по лямбда-выражению Java: Функциональное программирование на Java

Поскольку более 60% профессиональных разработчиков все еще используют Java 8 в начале 2021 года, понимание т… Помеченный как java, функциональный, учебник, лямбда.

Поскольку более 60% профессиональных разработчиков все еще используют Java 8 в начале 2021 года, понимание функций Java 8 является необходимым навыком. Java 8 была выпущена в 2014 году, принеся с собой множество новых функций.

Среди этих изменений были функции, которые позволяли разработчикам Java писать в функциональном стиле программирования. Одним из самых больших изменений стало добавление лямбда-выражений.

Лямбды похожи на методы, но им не нужно имя и они могут быть реализованы вне классов. В результате они открывают возможности для полнофункциональных программ и прокладывают путь для более функциональной поддержки Java в будущем.

Сегодня мы поможем вам начать работу с лямбда-выражениями и рассмотрим, как их можно использовать с интерфейсами.

Вот что мы рассмотрим сегодня:

  • Что такое лямбда-выражения?
  • Как написать лямбда-выражение
  • Интерфейсы на Java
  • Чему учиться дальше

Переподготовка для разработчика Java

Быстро осваивайте навыки работы на Java с помощью практической практики.

Java для программистов

Что такое лямбда-выражения?

Лямбда-выражения являются анонимной функцией, что означает, что у них нет имени или идентификатора. Они могут быть переданы в качестве параметра другой функции. Они сопряжены с функциональным интерфейсом и содержат параметр с выражением, которое ссылается на этот параметр.

Синтаксис базового лямбда-выражения таков:

parameter -> expression

Выражение используется в качестве тела кода для абстрактного метода (именованного, но пустого метода) в сопряженном функциональном интерфейсе.

В отличие от большинства функций в Java, лямбда-выражения существуют вне области видимости любого объекта. Это означает, что они могут вызываться в любом месте программы и могут передаваться по кругу. Проще говоря, лямбда-выражения позволяют функциям вести себя как просто еще один фрагмент данных.

Примеры использования лямбды в Java

Лямбда-выражения используются для достижения функциональности анонимного класса без загроможденной реализации. Они отлично подходят для повторения простых действий, которые можно использовать в нескольких областях программы, например, для добавления двух значений без изменения входных данных.

Эти свойства делают лямбду особенно полезной для функционального программирования стилей в Java. До появления Java 8 Java изо всех сил пыталась найти инструменты, отвечающие всем принципам функционального программирования.

Функциональное программирование имеет 5 ключевых принципов:

  • Чистые функции : Функции, которые работают независимо от состояния вне функции и содержат только те операции, которые необходимы для поиска выходных данных.

  • Неизменяемость : на входные данные ссылаются, а не изменяются. Функции должны избегать сложного условного поведения. В общем случае все функции должны возвращать одно и то же значение независимо от того, сколько раз оно вызывается.

  • Функции первого класса : Функции обрабатываются так же, как и любое другое значение. Вы можете заполнять массивы функциями, передавать функции в качестве параметров и т.д.

  • Функции высшего порядка : функции высшего порядка либо одна, либо несколько функций в качестве параметров, либо возвращают функцию. Они необходимы для создания сложных моделей поведения с помощью функционального программирования.

  • Композиция функций : Несколько простых функций могут быть объединены в разных порядках для создания сложных функций. Простые функции выполняют один шаг, который может быть разделен между несколькими задачами, в то время как сложные функции выполняют целую задачу.

Лямбда-выражения помогают нам достичь чистых функций, неизменяемости и принципов первоклассных функций в Java.

Лямбда-функции являются чистыми, поскольку они не зависят от определенной области видимости класса. Они неизменяемы, поскольку ссылаются на переданный параметр, но не изменяют значение параметра для достижения своего результата. Наконец, это первоклассные функции, потому что они могут быть анонимными и передаваться другим функциям.

Лямбда-выражения также используются в качестве прослушивателей событий и функций обратного вызова в нефункциональных программах из-за их независимости от класса.

Как написать лямбда-выражение на Java

Как мы видели ранее, основная форма лямбда-выражения передается одним параметром.

parameter -> expression

Одно лямбда-выражение также может иметь несколько параметров:

    (parameter1, parameter2) -> expression

Сегмент выражения, или тело лямбды, содержит ссылку на параметр. Значение лямбда-выражения – это значение выражения при выполнении с переданными параметрами.

Например:

import java.util.ArrayList;

public class main {
  public static void main(String[] args) {
    ArrayList numbers = new ArrayList();
    numbers.add(5);
    numbers.add(9);
    numbers.add(8);
    numbers.add(1);
    numbers.forEach( (n) -> { System.out.println(n); } );
  }
}

Параметр n передается в выражение System.out.println(n) . Затем выражение выполняется с использованием значения параметра n в заявлении для печати. Это повторяется для каждого числа в списке массивов, передавая каждый элемент списка в лямбда-выражение как n . Таким образом, результатом этого выражения является печатный список элементов Arraylist: 5 9 8 1 .

Тело Лямбда-функции

Тело лямбда-функции может содержать выражения в нескольких строках, если оно заключено в фигурные скобки.

Например:

 (oldState, newState) -> {
    System.out.println("Old state: " + oldState);
    System.out.println("New state: " + newState);
  }

Это позволяет использовать более сложные выражения, которые выполняют блоки кода, а не один оператор.

Вы также можете выполнять возврат из лямбда-функций, добавив оператор return в тело функции.

   public static Addition getAddition() {
      return (a, b) -> a + b; // lambda expression return statement
   }

У лямбды даже есть свой собственный оператор возврата:

(a, b) -> a + b;

Компилятор предполагает, что a+b является нашим возвращаемым значением. Этот синтаксис более чистый и будет выдавать тот же результат, что и в предыдущем примере.

Независимо от того, насколько длинным или сложным становится выражение, помните, что лямбда-выражения должны немедленно выводить согласованное значение. Это означает, что выражение не может содержать никаких условных операторов, таких как если или в то время как и не может дождаться ввода пользователя.

Весь код в выражении должен иметь неизменяемый вывод независимо от того, сколько раз он выполняется.

Лямбды как объекты

Вы можете отправлять лямбды другим функциям в качестве параметров. Представьте, что мы хотим создать программу приветствия, открытую для добавления дополнительных функций приветствия на разных языках.

// WellWisher.java
public class WellWisher {
    public static void wish(Greeting greeting) {
        greeting.greet();
    }
    // Passing a lambda expression to the wish method
    public static void main(String args[]) {
        wish( () -> System.out.println("Namaste") );
    }
}
// Greeting.java
@FunctionalInterface
public interface Greeting {
    void greet();
}

Здесь передается само выражение, и немедленно выполняется функция great(); . Отсюда мы можем добавить дополнительные функции приветствия для разных языков, которые будут переопределять печать только правильного приветствия.

Продолжайте изучать современную Java.

Java по-прежнему остается одним из самых востребованных языков современными компаниями. Образовательные программы дают вам всю практическую практику, необходимую для повторного обучения в два раза быстрее.

Java для программистов

Интерфейсы на Java

Интерфейсы в Java похожи на классы. Это чертежи, содержащие переменные и методы. Однако интерфейсы содержат только абстрактные методы, которые имеют сигнатуры, но не имеют реализации кода.

Интерфейсы можно рассматривать как список атрибутов или методов, которые реализующий класс должен определить для работы. В интерфейсе указано, какими функциями он должен обладать, но не указано, как их реализовать.

Например, у вас может быть интерфейс Персонаж , в котором перечислены методы для всех вещей, которые должен уметь делать персонаж в видеоигре. В интерфейсе указано, что у всех персонажей должен быть метод move() , но определение расстояния и средств передвижения (полет, бег, скольжение и т. Д.) зависит от класса отдельных персонажей.

Синтаксис интерфейса таков:

interface  {

    // declare constant fields
    // declare methods that abstract 
    // by default.
}

С интерфейсами классы Java обеспечивают множественное наследование, поскольку они не применяются к ограничению наследования одного класса. Это также помогает нам достичь полной абстракции, поскольку интерфейс по умолчанию не содержит области видимости или значений.

Лямбда-выражения используются для выражения экземпляра этих интерфейсов. До Java 8 нам приходилось создавать внутренний анонимный класс для использования этих интерфейсов.

// functional interface before java8

class Test 
{ 
    public static void main(String args[]) 
    { 
        // create anonymous inner class object 
        new Thread(new Runnable() 
        { 
            @Override
            public void run() // anonymous class
            { 
                System.out.println("New thread created"); 
            } 
        }).start(); 
    } 
} 
// functional interface using lambda expressions 

class Test 
{ 
  public static void main(String args[]) 
  { 

    // lambda expression to create the object 
    new Thread(()-> 
       {System.out.println("New thread created");}).start(); 
  } 
} 

Функциональные Интерфейсы

Лямбда-выражения могут реализовывать только функциональные интерфейсы , которые представляют собой интерфейс только с одним абстрактным методом. Лямбда-выражение, по сути, предоставляет тело абстрактного метода в функциональном интерфейсе.

Если бы интерфейс имел более одного абстрактного метода, компилятор не знал бы, какой метод должен использовать лямбда-выражение в качестве своего тела. Распространенными примерами встроенных функциональных интерфейсов являются Компаратор или Предикат .

Лучше всего добавлять необязательную аннотацию @FunctionalInterface в верхнюю часть любого функционального интерфейса.

Java понимает аннотацию как ограничение того, что отмеченный интерфейс может иметь только один абстрактный метод. Если существует более одного метода, компилятор отправит сообщение об ошибке.

Использование аннотации гарантирует отсутствие неожиданного поведения лямбда-выражений, вызывающих этот интерфейс.

@FunctionalInterface
interface Square 
{ 
    int calculate(int x); 
} 

Методы по умолчанию в интерфейсах

В то время как функциональные интерфейсы имеют ограничение на абстрактные методы, нет ограничений на стандартные или статические методы . Методы по умолчанию или статические методы могут точно настраивать наши интерфейсы для совместного использования различных поведений с наследующими классами.

Методы по умолчанию могут иметь тело внутри интерфейса. Самое главное, что методы по умолчанию в интерфейсах предоставляют дополнительные функциональные возможности для данного типа без разрушения реализующих классов.

До Java 8, если в интерфейсе был введен новый метод, все реализующие классы ломались. Чтобы исправить это, нам нужно было бы индивидуально обеспечить реализацию этого метода во всех реализующих классах.

Однако иногда методы имеют только одну реализацию, и нет необходимости предоставлять их реализацию в каждом классе. В этом случае мы можем объявить этот метод по умолчанию в интерфейсе и предоставить его реализацию в самом интерфейсе.

public interface Vehicle {
    void cleanVehicle();
    default void startVehicle() {
        System.out.println("Vehicle is starting");
    }
}

Здесь метод по умолчанию – запустить транспортное средство() , в то время как очистить транспортное средство() является абстрактным. Независимо от реализующего класса, запуск транспортного средства() всегда будет выводить одну и ту же фразу. Поскольку поведение не меняется в зависимости от класса, мы можем просто использовать метод по умолчанию, чтобы избежать повторного кода.

Самое главное, что интерфейс Vehicle по-прежнему имеет только 1 абстрактный метод и поэтому считается функциональным интерфейсом, который можно использовать с лямбда-выражениями.

Статические методы в интерфейсах

Статические методы в интерфейсах аналогичны методам по умолчанию, но их нельзя переопределить. Статические методы хороши, когда вы хотите, чтобы реализация метода оставалась неизменной при реализации классов.

// Car.java
public abstract class Car implements Vehicle {
    public static void repair(Vehicle vehicle){
        vehicle.repairVehicle();
    }
    public static void main(String args[]){

        Vehicle.cleanVehicle(); //This will compile.
        Car.repair(() -> System.out.println("Car repaired"));
    }
}
// Vehicle.java
//functional interface
public interface Vehicle {
    static void cleanVehicle(){
        System.out.println("I am cleaning vehicle");
    }
    void repairVehicle();
}

В классе Car мы можем вызвать clean Vehicle() для создания реализации, определенной в нашем интерфейсе. Если мы попытаемся @@@@Переопределите метод cleanVehicle() , мы получим сообщение об ошибке, потому что он был объявлен статическим .

Наконец, мы все еще можем использовать этот интерфейс в наших лямбда-выражениях, потому что repairVehicle() является нашим единственным абстрактным методом.

Чему учиться дальше

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

Некоторые функции, которые необходимо изучить далее, следующие:

  • Потоковый API
  • Дополнения API параллелизма
  • Инструменты для обработки массовых данных
  • Встроенные функции более высокого порядка

Чтобы помочь вам освоить Java 8 и усовершенствовать свои навыки работы с Java, мы собрали Java для программистов Путь обучения . Эти кураторские модули охватывают все основы программирования Java, такие как ООП , многопоточность , рекурсия и глубокое погружение во все основные изменения в Java 8.

К концу у вас будет практический опыт владения навыками, необходимыми для современных собеседований.

Счастливого обучения!

Продолжайте изучать Java 8 и функциональное программирование

Оригинал: “https://dev.to/educative/java-lambda-expression-tutorial-functional-programming-in-java-466f”