Разделить заказы пациента по условиям

Рейтинг: 1Ответов: 1Опубликовано: 06.03.2023

Есть коллекция с заказами клиентов.

List<Order> orderList;

Order содержит следующие поля: id_client - уникальный номер клиента status - Статус заказа cito - Срочность заказа

Как можно разделить заказы клиента по условию что если у одного клиента были заказы с одним статусом и cito в одну коллекцию, а другие в другую коллекцию?

Класс Order

public class Order {
    private int client_id;
    private int type;
    private String city;

    public Order() {

    }

    public int getClient_id() {
        return client_id;
    }

    public void setClient_id(int client_id) {
        this.client_id = client_id;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }
}

Ответы

▲ 2Принят

Для решения таких задач удобно использовать Stream API, в котором поток заказов Stream<Order> группируется по идентификатору клиента, а затем заказы дополнительно делятся по условию на две коллекции при помощи коллектора Collectors.partitioningBy, для которого нужно передать функцию-предикат.

Таким образом, получается мапа Map<Long, Map<Boolean, List<Order>>>.

Пример реализации (с использованием Lombok-аннотаций):

// пример класса Order
@Data
@AllArgsConstructor
class Order {
    private long idClient;
    private String status;
    private String urgency;
}
public static Map<Long, Map<Boolean, List<Order>>> groupByClientAndCondition(List<Order> orders, Predicate<Order> condition) {
    return orders.stream()
            .collect(Collectors.groupingBy(
                    Order::getIdClient,
                    LinkedHashMap::new,
                    Collectors.partitioningBy(condition)
            ));
}

Тест:

List<Order> orders = Arrays.asList(
        new Order(1001L, "ok", "none"),
        new Order(1002L, "cito", "asap"),
        new Order(1001L, "cito", "urgent!"),
        new Order(1010L, "usual", null)
);

groupByClientAndCondition(orders, order -> "cito".equals(order.getStatus()))
        .forEach((clientId, groups) -> System.out.printf("%d:%n\tcito: %s%n\tother: %s%n---%n", clientId, groups.get(true), groups.get(false)));
1001:
    cito: [Order(idClient=1001, status=cito, urgency=urgent!)]
    other: [Order(idClient=1001, status=ok, urgency=none)]
---
1002:
    cito: [Order(idClient=1002, status=cito, urgency=asap)]
    other: []
---
1010:
    cito: []
    other: [Order(idClient=1010, status=usual, urgency=null)]
---

При необходимости большей детализации список заказов можно группировать отдельно по каждому статусу и другим полям, используя Collectors.groupingBy вместо Collectors.partitioningBy, соответственно ключом во вложенной мапе будет тип поля статуса.