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

Примеры Java 8 – Stream.map()

В этом уроке мы рассмотрели примеры использования метода Stream.map() в Java 8. Мы включили обновление по потокам и перешли к практическим примерам.

Автор оригинала: Mila Lukic.

Вступление

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

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

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

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

Типы потоков

Потоки могут быть последовательно (созданы с потоком () ) или параллельно (созданы с параллельным потоком() ). Параллельные потоки могут работать с несколькими потоками, в то время как последовательные потоки не могут.

Операции с потоками могут быть либо промежуточными , либо терминальными :

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

  • map(op) – Возвращает новый поток, в котором предоставленная функция options применяется к каждому из элементов исходного потока
  • фильтр(cond) – Возвращает новый поток , который содержит только элементы из исходного потока, удовлетворяющие условию cond , заданному предикатом
  • сортировка() – Возвращает исходный поток, но с отсортированными элементами

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

Некоторые из терминальных операций являются:

  • collect() – Возвращает результат промежуточных операций, выполненных над исходным потоком
  • forEach() – Метод void, используемый для итерации по потоку
  • reduce() – Возвращает один результат, полученный из всей последовательности элементов в исходном потоке

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

Примеры Stream.map()

Давайте рассмотрим пару примеров и посмотрим, что мы можем сделать с операцией map () .

Поток целых чисел в поток строк

Arrays.asList(1, 2, 3, 4).stream()
        .map(n -> "Number " + String.valueOf(n))
        .forEach(n -> System.out.println(n + " as a " + n.getClass().getName()));

Здесь мы составили список целых чисел и вызвали stream() в списке, чтобы создать новый поток данных. Затем мы сопоставили каждое число n в списке с помощью метода map() в строку. Строки просто состоят из "Числа" и String.valueOf(n) .

Таким образом, для каждого числа в нашем исходном списке теперь у нас будет строка "Число n" , соответствующая ему.

Поскольку map() снова возвращает Поток , мы использовали метод forEach() для печати каждого элемента в нем.

Выполнение этого кода приводит к:

Number 1 as a java.lang.String
Number 2 as a java.lang.String
Number 3 as a java.lang.String
Number 4 as a java.lang.String

Примечание: Это ни в малейшей степени не изменило исходный список. Мы просто обработали данные и распечатали результаты. Если бы мы хотели сохранить это изменение, мы бы собрали() данные обратно в Коллекцию объект, такой как Список , Карта , Набор и т. Д:

List list = Arrays.asList(1, 2, 3, 4);
		
List mappedList = list.stream()
        .map(n -> "Number " + String.valueOf(n))
        .collect(Collectors.toList());

System.out.println(list);
System.out.println(mappedList);

Это приводит к:

[1, 2, 3, 4]
[Number 1, Number 2, Number 3, Number 4]

Поток строк в поток целых чисел

Теперь давайте сделаем это наоборот – преобразуем поток строк в поток целых чисел:

Arrays.asList("1", "2", "3", "4").stream()
        .map(n -> Integer.parseInt(n))
        .forEach(n -> System.out.println(n));

Как и ожидалось, этот код выдаст следующий результат:

1
2
3
4

Список объектов в Список других объектов

Допустим, у нас есть класс Точка , представляющий одну точку в декартовой системе координат:

public class Point {
    int X;
    int Y;
    
    Point(int x, int y){
        this.X=x;
        this.Y=y;
    }
    
    @Override
    public String toString() {
        return "(" + this.X + ", " + this.Y + ")";
    }
    
}

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

Git Essentials

Ознакомьтесь с этим практическим руководством по изучению Git, содержащим лучшие практики и принятые в отрасли стандарты. Прекратите гуглить команды Git и на самом деле изучите это!

Затем, поскольку мы хотели бы использовать новые координаты, мы соберем эти данные в новый список масштабированных точек:

List originalPoints = Arrays.asList(new Point(1, 2),
                                           new Point(3, 4),
                                           new Point(5, 6),
                                           new Point(7, 8));
System.out.println("Original vertices: " + originalPoints);
    
List scaledPoints = originalPoints
        .stream()
        .map(n -> new Point(n.X * 2, n.Y * 2))
        .collect(Collectors.toList());

System.out.println("Scaled vertices: " + scaledPoints);

В этом примере будет получен следующий результат:

Original vertices: [(1, 2), (3, 4), (5, 6), (7, 8)]
Scaled vertices: [(2, 4), (6, 8), (10, 12), (14, 16)]

Вывод

В этой статье мы объяснили, что такое потоки в Java. Мы упомянули некоторые из основных методов, используемых в потоках, и сосредоточились конкретно на методе map() и на том, как его можно использовать для манипулирования потоками.

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