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

Мои наиболее часто используемые лямбда-функции Java 8

Введение Java 8 запустила одну из своих лучших функций: лямбда-функции – первый шаг o… Помеченный java, функциональный, для начинающих.

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

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

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

List ints = Arrays.asList(12, 32, 1, 3, 5, 3, 10, 8, 100);

List filteredElements = ints.stream().filter(element -> element > 10)
        .collect(Collectors.toList());

Как можно заметить, код довольно прост: создается список целых чисел ints , затем вызывается метод stream() . Это обеспечивает возможность использования функционального программирования, уже встроенного. Здесь используется метод filter(...) , и он выполняет следующие действия:

  • для каждого элемента в коллекции ints применяется логическая функция. В этом случае он проверяет, превышает ли каждый элемент 10: элемент > 10 . Когда это верно, элемент передается обрабатываемому следующему функциональному методу.

Далее|/| .собирать (коллекционеры.Применяется функция ToList()) , которая преобразует результат фильтра(…) в список целых чисел, представленных переменной: filteredElements . Ниже приведен результат печати результирующей коллекции (вспомогательные методы используются для красивой печати результатов в статье, но они не перечислены, потому что они довольно просты):

Filter Integers higher than 10: [12, 32, 100]

Обратите внимание, насколько проще и понятнее использование метода filter(...) . Только с первого взгляда разработчик может понять назначение метода. Это гораздо легче читать, чем взаимодействие через набор целых чисел и добавление в новый список только тех элементов, которые превышают 10. Кроме того, он менее многословен.

Метод фильтрации также может быть применен к параметрам объекта, как показано ниже:

List peopleList = Person.createPersonList();

    List
        filteredPersonList =
        peopleList.stream().filter(person -> person.getAge() > 30).collect(Collectors.toList());

Здесь он фильтруется из списка, только элементы объекта Человек , у которого параметр возраст превышает 30. Лицо объекта определено ниже (обратите внимание, что функция Также отображается createPersonList() ):

public class Person {
  private int age;
  private String name;

  public Person(int age, String name) {
    this.age = age;
    this.name = name;
  }

  @Override
  public String toString() {
    return "Person{" +
        + age +
        ", name='" + name + '\'' +
        '}';
  }

  @Override
  public int hashCode() {
    return Objects.hash(age, name);
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public boolean isPersonCool() {
    return this.age > 40;
  }

  public static List createPersonList() {
    List personList = new ArrayList<>();

    personList.add(new Person(18, "Little person"));
    personList.add(new Person(25, "Young adult"));
    personList.add(new Person(33, "Responsible adult"));
    personList.add(new Person(45, "Almost grandfather"));
    personList.add(new Person(60, "Mein Opa"));

    return personList;
  }
}

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

List peopleList = Person.createPersonList();

    List
        filteredPersonList =
        peopleList.stream().filter(Person::isPersonCool).collect(Collectors.toList());

Обратите внимание, как обозначение Случаи::функция может использоваться для упрощения обозначения, когда булева функция применяется как Человек::Человек классный . Это улучшает читабельность и делает код более чистым. Поскольку кто-то крутой – это человек старше 40 лет, результатом выполнения описанной выше функции является:

Filter by cool people: [Person{age=45, name='Almost grandfather'}, Person{age=60, name='Mein Opa'}]

Еще одна полезная задача для списков – сопоставление одного объекта с другим. Такая деятельность также может быть легко выполнена с помощью лямбда-функций. В следующем примере список объектов Человек будет сопоставлен с объектами Супергерой . Ниже приведена реализация класса Супергерой :

public class Superhero {
  private int age;
  private String name;
  private String superPower;

  public Superhero(int age, String name, String superPower) {
    this.age = age;
    this.name = name;
    this.superPower = superPower;
  }

  @Override
  public String toString() {
    return "Superhero{" +
        + age +
        ", name='" + name + '\'' +
        ", superPower='" + superPower + '\'' +
        '}';
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getSuperPower() {
    return superPower;
  }

  public void setSuperPower(String superPower) {
    this.superPower = superPower;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }
}

А вот карта(...) пример использования:

List superheroes = personList
        .stream()
        .map(person -> new Superhero(person.getAge(), person.getName(), "fly")).collect(
        Collectors.toList());

В приведенном выше коде вот что происходит:

  • для каждого экземпляра объекта Person создается новый экземпляр Супергероя с параметрами возраст и имя от связанного Человека , и с третьим параметром летать как сверхдержава.
  • Каждый экземпляр Супергероя затем передается следующей лямбда-функции для обработки.
  • Затем функция collect (Коллекторы.Применяется ToList()) . Он собирает результат предыдущего преобразования (сопоставления) и помещает в Список объектов Супергероя .

Результат преобразования, изображен ниже:

Map ordinary people to superheroes: [Superhero{age=18, name='Little person', superPower='fly'}, Superhero{age=25, name='Young adult', superPower='fly'}, Superhero{age=33, name='Responsible adult', superPower='fly'}, Superhero{age=45, name='Almost grandfather', superPower='fly'}, Superhero{age=60, name='Mein Opa', superPower='fly'}]

До сих пор фильтрация и сопоставление данных применялись отдельно. Однако ничто не запрещает использовать их вместе, как показано в примере ниже:

List coolSuperheroes =
        Person.createPersonList().stream()
            .filter(Person::isPersonCool)
            .map(coolPeople -> new Superhero(coolPeople.getAge(), coolPeople.getName(), "be invisible"))
            .collect(Collectors.toList());

В приведенном выше примере список Людей фильтруется по критериям, кто крут, по использованию функции Человек::Человек Классный . После этого все крутые люди превращаются в супергероев , используя отображение: .карта(крутые люди ->новый супергерой(coolpeople.getAge(), coolPeople.getName(), "быть невидимым")) . Последним шагом является сбор списка Супергероев объектов с помощью .коллекционировать (Коллекционеры.тоЛист ()) . Результат обсуждаемого кода можно увидеть ниже:

Filter by coolness and map to superheroes: [Superhero{age=45, name='Almost grandfather', superPower='be invisible'}, Superhero{age=60, name='Mein Opa', superPower='be invisible'}]

Выполнение арифметических действий с данными коллекций – еще одно распространенное действие в коллекции. Конечно, это также поддерживается лямбда-функциями.

Ниже приведен пример, в котором суммируются все элементы целочисленного списка:

List integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

    int sumResult = integers.stream().mapToInt(Integer::intValue).sum();

В приведенном выше примере сначала список целых чисел вызывает метод stream() , чтобы получить доступ к лямбда-функциям. Затем каждый элемент сопоставляется целому числу. Таким образом, у вас есть доступ к функции sum() , которая, как следует из ее названия, суммирует все элементы в отображенной функции. Результат показан ниже:

Sum ints using IntStream.sum(): 45

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

  • для списка l , есть значение аккумулятора a . Каждый элемент списка называется e .

    • функция сокращения r применяется к каждому элементу e . Функция r имеет в качестве своего первого параметра аккумулятор a и текущее значение списка e . Функция уменьшения имеет в качестве возвращаемого значения новый накопитель a , который является результатом того, какой алгоритм использовался для функции уменьшения r .

Действительно, приведенное выше определение является довольно общим и трудным для понимания. Поэтому смотрите пример ниже, который сделает все намного более понятным:

List integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

    int sumResult = integers.stream().reduce(0, (a, e) -> a + e);```
{% endraw %}


Note the reduce function {% raw %}`r`{% endraw %} sums the previous accumulator value {% raw %}`a`{% endraw %} with the current element {% raw %}`e`{% endraw %}. So, for each element of the list, its value is summed to the total already calculated before. The initial value for the accumulated value {% raw %}`a`{% endraw %} is zero, as defined here: {% raw %}`reduce(0, (a, e) -> a + e)`{% endraw %}.

Other interesting functions are provided, such as calculating the average of a list of numbers:
{% raw %}


```java
List integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

    OptionalDouble meanResult = integers.stream().mapToInt(Integer::intValue).average();

Вычисление максимального значения списка:

List integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

    OptionalInt maxResult = integers.stream().mapToInt(Integer::valueOf).max();

И, конечно же, расчет минимального:

List integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

    OptionalInt minResult = integers.stream().mapToInt(Integer::valueOf).min();

Как и ожидалось, все три обсуждаемых типа лямбда-функций могут быть объединены, как в примере ниже:

OptionalDouble averageAge = Person.createPersonList().stream()
        .filter(Person::isPersonCool)
        .map(coolPeople -> new Superhero(coolPeople.getAge(), coolPeople.getName(), "be invisible"))
        .mapToInt(Superhero::getAge)
        .average();

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

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

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

Вы можете найти весь исходный код, используемый в этой статье здесь .

Оригинал: “https://dev.to/dufernandes/my-most-used-java-8-lambda-functions-269i”