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

Давайте поговорим о ПОТОКАХ!!

Эй, там! В этой статье я расскажу о потоках в Java и о том, как они помогают мне… С тегами java, новички, учебник, карьера.

Эй, там!

В этой статье я расскажу о потоках в Java и о том, как они помогают в написании аккуратных и компактных производственных кодов.

Но прежде чем погрузиться в потоки, давайте немного поговорим о Функциональном программировании

Нас, разработчиков Java, постоянно спрашивают о подробном характере Java и о том, как даже напечатать одно слово, которое мы должны написать примерно в 5-8 строках кода. 😭

Ну, это был сценарий до того, как появилась JAVA 8. С включением функционального программирования детализация кода JAVA может быть уменьшена примерно до 70%. 😮

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

🎯 Что такое функциональное программирование ❓

Функциональное программирование (также называемое FP) – это способ мышления о создании программного обеспечения путем создания чистых функций. Это позволяет избежать концепций общего состояния, изменяемых данных, наблюдаемых в объектно-ориентированном программировании.

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

🎯 Характеристики функционального программирования:

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

  • Данные неизменяемы
  • Функциональное программирование Разбивает проблему на “функции
  • Он построен на концепции математических функций, которая использует условные выражения и рекурсию для выполнения вычислений
  • Он не поддерживает итерации, такие как операторы цикла и условные операторы, такие как If-Else

🎯 Преимущества функционального программирования:

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

Итак, теперь у нас есть базовая идея функционального программирования! Давайте посмотрим, как это реализовано в Потоки JAVA

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

Поток не хранит данные и в этом смысле не является структурой данных. Он также никогда не изменяет базовый источник данных.

Эта функциональность – java.util.stream – поддерживает операции функционального стиля над потоками элементов, такие как преобразования с уменьшением карты в коллекциях.

✅ Прежде чем начать с потоками, давайте запишем некоторые важные понятия:

1.Поток – это поток данных, полученных из коллекции 2.Поток может создавать конвейер функций, которые могут быть оценены 3. Данные в потоке оцениваются лениво 4.Поток может преобразовывать данные, но не может изменять их.

🎯 [ПРИМЕЧАНИЕ] – Поток не является структурой данных. Кроме того, структура данных, на которой вы создаете поток, вообще не изменяется. Поток просто (своего рода) делает его копию и выполняет некоторые действия над своей собственной копией.

Ну, это все хорошо, но как создать поток ? 😕

🎯 Создание потока:

Отметьте галочкой Давайте сначала получим поток из существующего массива:

private static Dev[] arrayOfDevs = {
    new Dev(1, "Steve Rogers", 100000.0), 
    new Dev(2, "Anthony Stark", 200000.0), 
    new Dev(3, "Bruce Wayne", 300000.0)
};

Stream.of(arrayOfDevs);

Отметьте галочкой Мы также можем получить поток из существующего списка:

private static List devList = Arrays.asList(arrayOfDevs);
devList.stream();
  1. И мы можем создать поток из отдельных объектов, используя Stream.of():
Stream.of(arrayOfDevs[0], arrayOfDevs[1], arrayOfDevs[2]);

✔️ Или просто с помощью Stream.builder():

Stream.Builder devStreamBuilder = Stream.builder();

devStreamBuilder.accept(arrayOfDev[0]);
devStreamBuilder.accept(arrayOfDev[1]);
devStreamBuilder.accept(arrayOfDev[2]);

Stream devStream = devStreamBuilder.build();

Итак, теперь мы знаем, как создать поток. 😎 Но что толку в Потоке, если мы не можем с ним поиграть.

🎯 Потоковые операции:

Давайте теперь рассмотрим некоторые распространенные обычаи и операции, которые мы можем выполнять на и с помощью поддержки потоков на этом языке.

✔️ Предначертание:

forEach() – простейшая и наиболее распространенная операция; она перебирает элементы потока, вызывая предоставленную функцию для каждого элемента.

Метод настолько распространен, что был введен непосредственно в Iterable, Map и т.Д:

@Test
public void whenIncrementSalaryForEachDev_thenApplyNewSalary() {    
    devList.stream().forEach(d -> d.salaryIncrement(10.0));

    assertThat(devList, contains(
      hasProperty("salary", equalTo(110000.0)),
      hasProperty("salary", equalTo(220000.0)),
      hasProperty("salary", equalTo(330000.0))
    ));
}

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

forEach() – это терминальная операция, которая означает, что после выполнения операции конвейер потока считается использованным и больше не может использоваться.

✔️ карта

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

Следующий пример преобразует поток целых чисел в поток разработчиков:

@Test
public void whenMapIdToDevs_thenGetDevStream() {
    Integer[] devIds = { 1, 2, 3 };

    List devs = Stream.of(devIds)
      .map(devRepository::findById)
      .collect(Collectors.toList());

    assertEquals(devs.size(), devIds.length);
}

Здесь мы получаем целочисленный поток дэвидов из массива. Каждое целое число передается функции devRepository::findById(), которая возвращает соответствующий объект разработки; это эффективно формирует поток разработки.

✔ collect собирать Мы видели, как работает collect() в предыдущем примере; это один из распространенных способов извлечь материал из потока, как только мы закончим всю обработку:

@Test
public void whenCollectStreamToList_thenGetList() {
    List devs = devList.stream().collect(Collectors.toList());

    assertEquals(devList, devs);
}

collect() выполняет операции с изменяемым сгибом (переупаковка элементов в некоторые структуры данных и применение некоторой дополнительной логики, их объединение и т.д.) К элементам данных, хранящимся в экземпляре потока.

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

✔️ фильтр

Далее давайте посмотрим на filter(); это создает новый поток, содержащий элементы исходного потока, которые проходят заданный тест (заданный предикатом).

Давайте посмотрим, как это работает:

@Test
public void whenFilterDevs_thenGetFilteredStream() {
    Integer[] devIds = { 1, 2, 3, 4 };

    List devs = Stream.of(devIds)
      .map(devRepository::findById)
      .filter(e -> e != null)
      .filter(e -> e.getSalary() > 200000)
      .collect(Collectors.toList());

    assertEquals(Arrays.asList(arrayOfDevs[2]), devs);
}

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

Отметьте галочкой toArray Мы видели, как мы использовали collect() для извлечения данных из потока. Если нам нужно извлечь массив из потока, мы можем просто использовать toArray():

@Test
public void whenStreamToArray_thenGetArray() {
    Dev[] devs = devList.stream().toArray(Dev[]::new);

    assertThat(devList.toArray(), equalTo(devs));
}

Синтаксис Dev[]::new создает пустой массив разработчиков, который затем заполняется элементами из потока.

🎯 [ПРИМЕЧАНИЕ]

Ленивая Оценка

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

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

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

Например, рассмотрим пример findFirst(), который мы видели ранее. Сколько раз здесь выполняется операция map()? 4 раза, так как входной массив содержит 4 элемента?

@Test
public void whenFindFirst_thenGetFirstDevInStream() {
    Integer[] devIds = { 1, 2, 3, 4 };

    Dev devs= Stream.of(devIds)
      .map(devRepository::findById)
      .filter(e -> e != null)
      .filter(e -> e.getSalary() > 100000)
      .findFirst()
      .orElse(null);

    assertEquals(devs.getSalary(), new Double(200000));
}

Поток выполняет сопоставление и две операции фильтрации, по одному элементу за раз.

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

Идентификатор 2 удовлетворяет обоим предикатам фильтра, и, следовательно, поток оценивает операцию терминала findFirst() и возвращает результат.

Никакие операции с идентификаторами 3 и 4 не выполняются.

Ленивая обработка потоков позволяет избежать проверки всех данных, когда в этом нет необходимости. Такое поведение становится еще более важным, когда входной поток бесконечен, а не просто очень велик.

Java Streams Api – очень большая тема, и я изо всех сил старался как можно больше вместить в этот пост. Пожалуйста, обратитесь к приведенным ниже ссылкам для получения более глубоких знаний.

👇

Ссылка для справки-1

Документы Oracle

Ссылка на Бельдунг

Devoxx Ютуб

Некоторые из моих других постов:

статья goto Модификаторы доступа Java
статья goto Дженерики Java
статья goto Регулярное выражение Java
статья goto Api потоков Java

Пожалуйста, оставьте ❤️ , если вам понравилась эта статья. A 🦄 было бы здорово. И дайте мне знать на панели обсуждений, если у вас есть какие-либо предложения для меня. И оставьте ссылку на любой известный вам ресурс по Api Java Streams, который может помочь другим, и я добавлю его в сообщение.

Хорошего вам дня! 😃

Оригинал: “https://dev.to/the_unconventional_coder/lets-talk-about-streams-2bdf”