Статьи

Разговорное руководство по лямбдам JDK8 — глоссарий терминов

Последнее появление … Я написал пост, связанный с новыми угощениями, которые JDK8 предлагает для нас. Скорее всего, особенность, которая меня больше всего волнует — это лямбды. Я должен признать, что в течение моего первого года, когда я был блудным человеком (в течение которого я разрабатывал с использованием C #), я любил LINQ и красивые, элегантные вещи, которые вы можете делать с ним. Теперь, даже если стирание все еще находится в том же месте, где мы его оставили в прошлый раз, теперь у нас есть лучший способ фильтровать, изменять, просматривать коллекции и помимо синтаксического сахара, это также может заставить вас правильно использовать четырехъядерный процессор что ты хвастался своим друзьям. И говоря о друзьях, этот пост представляет собой список терминов, связанных с лямбдами и потоковой обработкой, которые вы можете бросить своим друзьям, когда они спросят вас: «Что это за <место термина из JDK 8, связанное с лямбдами>?». Я не намерен иметь полный список или руководство по лямбде, если я сказал что-то не так или я что-то пропустил, пожалуйста, дайте мне знать …

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

Согласно [jls 8], функциональный интерфейс — это интерфейс, который имеет только один абстрактный метод и, таким образом, представляет один контракт функции (в некоторых случаях этот «единственный» метод может принимать форму нескольких абстрактных методов с переопределенными эквивалентными сигнатурами ( [jls7_8.4.2]) унаследовано от суперинтерфейсов, в этом случае унаследованные методы логически представляют один метод).

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

Пример:

1
interface Runnable { void run(); }

Интерфейс Runnable является очень подходящим примером, поскольку единственный присутствующий метод — это метод run . Другим «классическим» примером функционального интерфейса Java является интерфейс Comparator <T> , в следующем примере — ранее упомянутый интерфейс и метод equals, унаследованный от Object , интерфейс по-прежнему функционален, поскольку метод сравнения является единственным абстрактным методом, в то время как Равные унаследованы от суперкласса.

1
2
3
4
5
6
interface Comparator<T> {
 boolean equals(Object obj);
  
  int compare(T o1, T o2);
  
}

Ручей

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

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

Получение потоков:

  • Из Collection помощью методов stream() и / или parallelStream() ;
  • Из массива через Arrays.stream(Object[])
  • Из статических методов фабрики для потоковых классов, таких как Stream.of(Object[]) , IntStream.range(int, int) или Stream.iterate(Object, UnaryOperator) ;
  • Строки файла могут быть получены из BufferedReader.lines();
  • Потоки путей к файлам могут быть получены из методов в файлах;
  • Потоки случайных чисел можно получить из Random.ints();
  • Множество других потоковых методов в JDK, including BitSet.stream() , Pattern.splitAsStream(java.lang.CharSequence) и JarFile.stream() .

потоковые операции — действия, выполняемые в потоке. С точки зрения управления потоком существует два типа действий: промежуточные и терминальные операции.

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

  • фильтр — фильтрует поток на основе предоставленного предиката
  • map — создает новый поток, применяя функцию отображения к каждому элементу из исходного потока (соответствующие методы для каждого числового типа: int, long, double)
  • flatMap — операция, которая приводит к применению преобразования «один ко многим» к элементам потока, а затем сглаживает элементы результатов в новый поток. Например, если заказы представляют собой поток заказов на покупку, и каждый заказ на покупку содержит коллекцию отдельных позиций, то следующее создает поток отдельных позиций:
1
orderStream.flatMap(order -> order.getLineItems().stream())
  • Отличный — возвращает поток отдельных операций
  • sorted — возвращает поток отсортированных операций
  • peek — ориентированный на отладку метод, который возвращает поток, состоящий из элементов этого потока, при этом предусмотренное действие выполняется для каждого элемента

Пример:

01
02
03
04
05
06
07
08
09
10
11
12
list.stream()
 
  .filter(filteringFunction)
 
  .peek(e -> {System.out.println("Filtered value: " + e); });
 
  .map(mappingFunction)
 
  .peek(e -> {System.out.println("Mapped value: " + e); });
 
  .collect(Collectors.intoList());
  
  • limit — возвращает усеченную версию текущего потока (не более, чем предельное количество элементов)
  • substream — возвращает поток, состоящий из оставшегося элемента, начиная с начальной позиции или между startPosition и endPosition

операция потокового терминала — прохождение потока для получения результата или побочного эффекта. После выполнения операции терминала поток считается использованным (вызов другой операции для потребленного потока вызовет IllegalStateException ). Операции с терминалами носят нетерпеливый характер, за исключением iterator() и splititerator() которые предоставляют механизм расширения для тех, кто не находит нужную функцию в API.

  • forEach — применяет предоставленную операцию к каждому элементу потока. Также существует версия forEachOrdered
  • toArray — извлекает элементы потока в массив
  • уменьшить — метод уменьшения
  • собирать — изменчивый метод сокращения
  • min — вычисляет минимум потока
  • max — вычисляет максимум потока
  • count — считает элементы потока
  • anyMatch — возвращает true, если есть элемент, соответствующий заданным критериям
  • allMatch — возвращает true, если все элементы совпадают
  • noneMatch — возвращает true, если ни один из элементов не совпадает
  • findFirst — находит первый элемент, который соответствует предоставленному условию
  • findAny — возвращает элемент из потока

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

Spliterator — Spliterator для прохождения и разделения элементов источника. Можно использовать его для обхода, оценки количества элементов или разбить его на несколько разделителей

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

Пример: уменьшение с использованием суммы:

1
int sum = numbers.stream().reduce(0, (x,y) -> x + y);

или же

1
int sum = numbers.stream().reduce(0, Integer::sum);

Изменяемое сокращение — это операция, которая накапливает входные элементы в изменяемый контейнер результатов (StringBuilder или Collection) при обработке элементов в потоке.

Пример:

1
String concatenated = strings.reduce("", String::concat)

Предикат — функциональный интерфейс, который определяет, соответствует ли входной объект некоторым критериям

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

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

Итак … я желаю вам хорошего времени пришествия и счастливого / веселого / веселого, но самое главное, я желаю вам мирного Рождества!