Можно ли объединить два Java 8 потоков? - PullRequest
3 голосов
/ 19 марта 2020

Мне было интересно, смогу ли я присоединиться к двум предварительно отсортированным потокам (за один проход). Например, если у меня есть следующие Java классы:

public class Person { // constructor & getters ommitted
  private String name;
  private int salary;
  private List<Car> cars;
  public void addCar(Car c) { cars.add(c); }
}

public class Car { // constructor & getters ommitted
  private String owner;
  private String brand;
}

И у меня есть предварительно отсортированные потоки, как в:

Stream<Person> clients = Arrays.asList(
  new Person("Anne", 500), 
  new Person("Johnny", 340)
  ).stream();

Stream<Car> cars = Arrays.asList(
  new Car("Johnny", "Mazda"), 
  new Car("Johnny", "Fiat"), 
  new Car("Mary", "Volvo")
  ).stream();

Я хотел применить addCar() к Джонни с "Маздой" и "Фиатом". Для Анны нет машины, и Мэри не является клиентом.

Возможно ли объединить оба потока с помощью одного прохода по потокам?

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

EDIT : ожидаемый результат операции будет вызывать addCar() дважды для «Джонни»: один раз с «Маздой», один раз с «Фиатом».

Ответы [ 2 ]

2 голосов
/ 19 марта 2020

Боюсь, что невозможно эффективно решить эту задачу с помощью Stream API. Но вы все равно можете сделать это с помощью итераторов.

public static void addCars(Stream<Person> clients, Stream<Car> cars) {
    Iterator<Person> clientsIt = clients.iterator();
    Iterator<Car> carsIt = cars.iterator();
    Person client = null;
    while (carsIt.hasNext()) {
        Car car = carsIt.next();
        while (client == null || !client.getName().equals(car.getOwner())) {
            if(!clientsIt.hasNext()) return;
            client = clientsIt.next();
        }
        client.addCar(car);
    }
}
1 голос
/ 19 марта 2020

Предварительный расчет может помочь. Что-то вроде

Map<String, List<Car>> cars = Stream.of(
        new Car("Johnny", "Mazda"),
        new Car("Johnny", "Fiat"),
        new Car("Mary", "Volvo"))
        .collect(Collectors.groupingBy(Car::getOwner));

Stream.of(new Person("Anne", 500),
        new Person("Johnny", 340))
        .forEachOrdered(p -> cars.getOrDefault(p.getName(), 
                Collections.emptyList()).forEach(p::addCar));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...