Java. Примеры решения задач на потоки данных




Примеры решения задач на потоки данных, которыми есть объекты разработанных классов


Содержание


Поиск на других ресурсах:

1. Класс Car (Автомобиль). Пример
1.1. Условие задачи

Создать класс «Автомобиль». В классе должна храниться следующая информация:

  • название автомобиля;
  • год выпуска;
  • стоимость;
  • цвет;
  • объем двигателя.

Нужно создать набор автомобилей и выполнить следующие задачи:

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

Задачи решить с использованием прикладного интерфейса Stream API.

 

1.2. Решение

Текст программы, решающей данную задачу следующий.

import java.util.ArrayList;
import java.util.Comparator;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;

class Car {
  private String name; // название автомобиля
  private int year; // год выпуска
  private String color; // цвет
  private double volume; // объем двигателя
  private double price; // стоимость

  // Конструктор
  public Car(String _name, String _color, int _year,
  double _volume, double _price) {
    name = _name; year = _year; color = _color;
    volume = _volume; price = _price;
  }

  // Методы get()
  String getName() { return name; }
  int getYear() { return year; }
  String getColor() { return color; }
  double getVolume() { return volume; }
  double getPrice() { return price; }
}

public class StreamAPI {

  // 1. Показать все автомобили
  public static void PrintAllCars(ArrayList<Car> AL) {
    // 1. Получить поток Stream<Car>
    Stream<Car> stream = AL.stream();

    // 2. Реализовать стандартный функц. интерфейс Consumer<T>
    Consumer<Car> action = (n) -> {
      System.out.println(n.getName() + ", " + n.getColor() +
                         ", " + n.getPrice() + ", " + n.getYear() +
                         ", " + n.getVolume());
    };

    // 3. Вывести все автомобили
    stream.forEach(action);

    // 4. То же самое
    /*
      AL.stream().forEach((n) -> System.out.println(n.getName() + ", " +
        n.getColor() +    ", " +
        n.getPrice() + ", " +
        n.getYear() + ", " +
        n.getVolume())); 
    */
  }

  // 2. Показать все автомобили указанного цвета
  public static void PrintAllCarsColor(ArrayList<Car> AL, String color) {
    // 1. Получить поток
    Stream<Car> stream = AL.stream();

    // 2. Ссылка на Predicate<T>
    Predicate<Car> predicate = (car) -> {
      if (car.getColor()==color)
        return true;
      return false;
    };

    // 3. Получить новый поток согласно с предикатом
    Stream<Car> filterStream = stream.filter(predicate);

    // 4. Вывести новый отфильтрованный поток
    // 4.1. Ссылка на станд. интерфейс Consumer<T>
    Consumer<Car> action = (n) -> {
      System.out.println(n.getName() + ", " + n.getColor() +
                         ", " + n.getPrice() + ", " + n.getYear() +
                         ", " + n.getVolume());
    };

    // 4.2. Вывод каждого элемента методом forEach()
    filterStream.forEach(action);
  }

  // 3. Показать все автомобили дорожче указанной цены
  public static void PrintAllCarsPrice(ArrayList<Car> AL, double price) {
    // 1. Получить поток
    Stream<Car> stream = AL.stream();

    // 2. Ссылка на Predicate<T>
    Predicate<Car> predicate = (car) -> {
      if (car.getPrice()>price)
        return true;
      return false;
    };

    // 3. Получить новый поток согласно предикату
    Stream<Car> filterStream = stream.filter(predicate);

    // 4. Вывести новый отфильтрованный поток
    // 4.1. Ссылка на станд. интерфейс Consumer<T>
    Consumer<Car> action = (n) -> {
      System.out.println(n.getName() + ", " + n.getColor() +
                         ", " + n.getPrice() + ", " + n.getYear() +
                         ", " + n.getVolume());
      };

    // 4.2. Вывод каждого элемента методом forEach()
    filterStream.forEach(action);
  }

  // 4. Отобразить автомобили, чей год выпуска находится в указанном диапазоне
  public static void PrintAllCarsYear(ArrayList<Car> AL, int year1, int year2) {
    // 1. Объявить ссылку на Predicate<T> и присвоить этой ссылке лямбда-выражение
    Predicate<Car> predicate = (car) ->
      (car.getYear()>=year1)&&(car.getYear()<=year2);

    // 2. Получить результирующий поток согласно с предикатом
    Stream<Car> stream = AL.stream().filter(predicate);

    // 3. Вывести результирующий поток
    // 3.1. Объявить ссылку на стандартный функциональный интерфейс Consumer<T>
    Consumer<Car> action;

    // 3.2. Присвоить ссылке action лямбда-выражение, которое выводит информацию об автомобиле
    action = (car) -> {
      System.out.println(car.getName() + ", " + car.getColor() +
                         ", " + car.getYear() + ", " + car.getPrice() + ", " + car.getVolume());
    };

    // 3.3. Отобразить поток stream
    stream.forEach(action);
  }

  // 5. Отобразить автомобили отсортированные по цене
  public static void PrintCarsSortedByPrice(ArrayList<Car> AL) {
    // 1. Объявить ссылку на функциональный интерфейс Comparator<T>
    Comparator<Car> comparator;

    // 2. Присвоить ссылке лямбда-выражение, сравнивающее два значения
    comparator = (car1, car2) -> {
      // Лямбда-выражение должно вернуть результат типа int: <0, ==0, >0
      // Сортировка по убыванию: car2 - car1.
      return (int)(car2.getPrice()-car1.getPrice()); // Сравниваем стоимости
    };

    // 4. Получить отсортированный поток. Для сортировки использовать метод sorted().
    Stream<Car> sortedStream = AL.stream().sorted(comparator);

    // 5. Вывести поток
    // 5.1. Объявить ссылку на интерфейс Consumer<T> и присвоить ей лямбда-выражение,
    //     которое выводит данные об автомобиле
    Consumer<Car> action = (car) -> {
      System.out.println(
                         car.getName() + ", " +
                         car.getColor() + ", " +
                         car.getYear() + ", " +
                         car.getPrice() + ", " +
                         car.getVolume()
                        );
    };

    // 5.2. Отобразить поток sortedStream
    sortedStream.forEach(action);
  }

  public static void main(String[] args) {
    // 1. Сформировать тестируемый масив
    ArrayList<Car> AL = new ArrayList<Car>();
    AL.add(new Car("BMW", "Black", 2018, 2.2, 18800.0));
    AL.add(new Car("Audi", "Silver", 2017, 2.3, 20500.0));
    AL.add(new Car("Renault", "Red", 2018, 1.5, 11800.0));
    AL.add(new Car("Audi", "Silver", 2016, 2.5, 22800.0));
    AL.add(new Car("Renault", "Silver", 2017, 1.3, 10250.0));
    AL.add(new Car("VW", "Red", 2017, 2.3, 15800.0));
    AL.add(new Car("Mercedes", "White", 2018, 2.5, 25800.0));

    // 2. Вывести все автомобили
    StreamAPI.PrintAllCars(AL);

    // 3. Вывести автомобили указанного цвета
    System.out.println("---------------------------------");
    StreamAPI.PrintAllCarsColor(AL, "Silver");

    // 4. Отобразить автомобили дороже указанной цены
    System.out.println("---------------------------------");
    StreamAPI.PrintAllCarsPrice(AL, 20000.0);

    // 5. Отобразить автомобили, чей год выпуска находится в указанном диапазоне
    System.out.println("---------------------------------");
    StreamAPI.PrintAllCarsYear(AL, 2018, 2018);

    // 6. Отсортировать автомобили в порядке убывания стоимости
    System.out.println("---------------------------------");
    System.out.println("Sorting by descending sort");
    StreamAPI.PrintCarsSortedByPrice(AL);
  }
}

Результат выполнения программы:

BMW, Black, 18800.0, 2018, 2.2
Audi, Silver, 20500.0, 2017, 2.3
Renault, Red, 11800.0, 2018, 1.5
Audi, Silver, 22800.0, 2016, 2.5
Renault, Silver, 10250.0, 2017, 1.3
VW, Red, 15800.0, 2017, 2.3
Mercedes, White, 25800.0, 2018, 2.5
---------------------------------
Audi, Silver, 20500.0, 2017, 2.3
Audi, Silver, 22800.0, 2016, 2.5
Renault, Silver, 10250.0, 2017, 1.3
---------------------------------
Audi, Silver, 20500.0, 2017, 2.3
Audi, Silver, 22800.0, 2016, 2.5
Mercedes, White, 25800.0, 2018, 2.5
---------------------------------
BMW, Black, 2018, 18800.0, 2.2
Renault, Red, 2018, 11800.0, 1.5
Mercedes, White, 2018, 25800.0, 2.5
---------------------------------
Sorting by descending sort
Mercedes, White, 2018, 25800.0, 2.5
Audi, Silver, 2016, 22800.0, 2.5
Audi, Silver, 2017, 20500.0, 2.3
BMW, Black, 2018, 18800.0, 2.2
VW, Red, 2017, 15800.0, 2.3
Renault, Red, 2018, 11800.0, 1.5
Renault, Silver, 2017, 10250.0, 1.3

 

2. Работа с потоками объектов обобщенных (шаблонных) классов. Класс Point<T>. Пример
2.1. Условие задачи

Разработать обобщенный (шаблонный) класс Point, реализующий точку на координатной плоскости (x; y).

На основании разработанного класса Point создать набор объектов. Для созданного набора объектов реализовать следующие задачи:

  • получить точку (объект) с наибольшим значением координаты x;
  • создать новый поток чисел типа double. Каждое число является расстоянием от точки до начала координат. Полученный поток вывести на экран;
  • создать новый поток объектов. В потоке должны быть точки (объекты), расстояние от которых до начала координат более 5;
  • сортировать объекты в порядке убывания по критерию расстоянии от точки до начала координат.

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

При решении задачи использовать средства Stream API.

 

2.2. Решение

Текст программы, решающей данную задачу следующий.

import java.util.*;
import java.util.function.*;
import java.util.stream.*;

// Обобщенный шаблонный класс, реализующий точку на координатной плоскости
class Point<T extends Number> {
  // Внутренние поля класса
  private T x;
  private T y;

  // Конструктор
  public Point(T x, T y) {
    this.x = x; this.y = y;
  }

  // Методы доступа к полям класса
  public T getX() { return x; }
  public T getY() { return y; }
}

// Класс - решение задачи
class Solution {
  // 1. Получить точку (объект) с наибольшим значением координаты x
  public <T extends Number> Point<T> getMaxCoordX(ArrayList<Point<T>> AL) {
    // 1. Получить поток данных из массива
    Stream<Point<T>> stream = AL.stream();

    // Реализовать компаратор - метод сравнения, возвращающий <0, ==0, >0
    // в зависимости от того, больше ли координата x точки 2 за координату x точки 1
    Comparator<Point<T>> comparator;

    comparator = (point1, point2) -> {
      // получить координаты x точек point1, point2
      T x2 = point2.getX();
      T x1 = point1.getX();

      if (x2.doubleValue()>x1.doubleValue())
        return -1;
      if (x2.doubleValue()<x1.doubleValue())
        return 1;
      return 0;
    };

    // 3. Вычислить точку Point<T> с максимальным значением X
    Optional<Point<T>> maxPt = stream.max(comparator);

    // 4. Возвратить найденную точку
    return maxPt.get();
  }

  // Метод, формирующий новый поток типа double. Элементы потока есть
  // расстояниями от точки до начала координат.
  public <T extends Number> Stream<Double> getStreamLengthOrigin(ArrayList<Point<T>> AL) {
    // 1. Получить поток точек из массива AL
    Stream<Point<T>> stream = AL.stream();

    // 2. Сформировать функцию получения значения типа double из типа Point<T>
    // 2.1. Объявить ссылку на стандартный функциональный интерфейс Function<T, R>
    Function<Point<T>, Double> function;

    // 2.2. Сформировать лямбда-выражение, возвращающее расстояние от точки point до
    //     начала координат
    function = (point) -> {
      double x = point.getX().doubleValue();
      double y = point.getY().doubleValue();
      return (double)(Math.sqrt(x*x+y*y));
    };

    // 3. Использовать функцию function с помощью метода map()
    Stream<Double> streamOrigin = stream.map(function);

    // 4. Вернуть результат
    return streamOrigin;
  }

  // Создать новый поток объектов. В потоке должны быть точки (объекты),
  // расстояние от которых до начала координат больше 5.
  public <T extends Number> Stream<Point<T>> getPointsLength5(ArrayList<Point<T>> AL) {
    // 1. Получить поток точек из массива AL
    Stream<Point<T>> stream = AL.stream();

    // 2. Сформировать предикат (условие), которое будет использоваться при формировании
    //   нового потока
    // 2.1. Объявить ссылку на стандартный функциональный интерфейс Predicate<T>
    Predicate<Point<T>> predicate;

    // 2.2. Присвоить ссылке лямбда-выражение
    predicate = (point) -> {
      // вычислить расстояние length от точки до начала координат
      double x = point.getX().doubleValue();
      double y = point.getY().doubleValue();
      double length = Math.sqrt(x*x+y*y);

      // проверить значение length
      if (length>5.0)
        return true;
      return false;
    };

    // 3. Сформировать новый поток из потока stream
    Stream<Point<T>> streamLength5 = stream.filter(predicate);

    // 4. Вернуть результат
    return streamLength5;
  };

  // Отсортировать объекты в порядке убывания по критерию расстояния от точки
  // до начала координат.
  public <T extends Number> Stream<Point<T>> getSortedPoints(ArrayList<Point<T>> AL) {
    // 1. Получить поток точек из массива AL
    Stream<Point<T>> stream = AL.stream();

    // 2. Сформировать компаратор - метод, сравнивающий расстояния от двух точек до начала координат.
    //   Метод возвращает значение типа int соответственно <0, ==0, >0.
    Comparator<Point<T>> comparator = (point1, point2) -> {
      // 2.1. Определить расстояния от точек point1, point2 до начала координат
      double x1 = point1.getX().doubleValue();
      double y1 = point1.getY().doubleValue();
      double x2 = point2.getX().doubleValue();
      double y2 = point2.getY().doubleValue();
      double length1 = Math.sqrt(x1*x1+y1*y1);
      double length2 = Math.sqrt(x2*x2+y2*y2);

      // 2.2. Вернуть результат
      return (int)(length2-length1);
    };

    // 3. Вызвать метод сортировки
    Stream<Point<T>> sortedStream = stream.sorted(comparator);

    // 4. Вернуть отсортированный поток stream
    return sortedStream;
  }
}

public class StreamAPI {

  public static void main(String[] args) {
    // Этапы решения задачи
    // 1. Создать набор объектов типа Point(),
    //   значение координат сформировать случайным образом
    ArrayList<Point<Integer>> AL = new ArrayList<Point<Integer>>();
    Point<Integer> pt;
    int x, y;

    // создается 10 точек
    for (int i=0; i<10; i++) {
      x = (int)(Math.random()*10);
      y = (int)(Math.random()*10);
      pt = new Point<Integer>(x, y);
      AL.add(pt);
    }

    // Вывести массив точек на экран для контроля
    System.out.print("AL = [");
    for (Point<Integer> t : AL) {
      System.out.print("(" + t.getX() + "," + t.getY() + ") ");
    }
    System.out.println("]");

    // 2. Реализовать решение. Для этого нужно создать экземпляр класса
    //   Solution и по очереди вызвать методы этого экземпляра
    Solution solution = new Solution();

    // 2.1. Задача 1. Решение
    Point<Integer> maxPt = solution.getMaxCoordX(AL);

    System.out.println("Solution 1. Max Point.");
    System.out.println("maxPt = (" + maxPt.getX().intValue() +
                       ", " + maxPt.getY().intValue() + ")");

    // 2.2. Задача 2. Решение
    Stream<Double> streamOrigin = solution.getStreamLengthOrigin(AL);

    // Вывести поток streamOrigin на экран
    System.out.println("Solution 2. Array of lengths.");
    Consumer<Double> action = (n) -> {
      System.out.println(n + " ");
    };
    streamOrigin.forEach(action);

    // 2.3. Задача 3. Решение
    Stream<Point<Integer>> streamPoints = solution.getPointsLength5(AL);

    // Вывести результат задачи 3
    System.out.println("Solution 3. Points with length>5.0");
    Consumer<Point<Integer>> action2 = (point) -> {
      System.out.println("("+point.getX()+"; " + point.getY() + ")");
    };
    streamPoints.forEach(action2);

    // 2.4. Задача 4. Решение
    Stream<Point<Integer>> streamSorted = solution.getSortedPoints(AL);
    System.out.println("Solution 4. Sorting points.");

    // Вывести результат задачи 4
    streamSorted.forEach(action2);
  }
}

Результат выполнения программы

AL = [(9,2) (7,4) (3,3) (8,2) (4,7) (8,6) (0,1) (0,2) (4,6) (4,6) ]
Solution 1. Max Point.
maxPt = (9, 2)
Solution 2. Array of lengths.
9.219544457292887
8.06225774829855
4.242640687119285
8.246211251235321
8.06225774829855
10.0
1.0
2.0
7.211102550927978
7.211102550927978
Solution 3. Points with length>5.0
(9; 2)
(7; 4)
(8; 2)
(4; 7)
(8; 6)
(4; 6)
(4; 6)
Solution 4. Sorting points.
(9; 2)
(8; 6)
(7; 4)
(8; 2)
(4; 7)
(4; 6)
(4; 6)
(3; 3)
(0; 2)
(0; 1)

 


Связанные темы