Java 8: как выполнить проверку состояния между несколькими сравнениями

#java #lambda #java-8 #java-stream

#java #лямбда #java-8 #java-stream

Вопрос:

Мне нужно отсортировать коллекцию с несколькими условиями. Но между этими условиями мне нужно изменить данные потока.

Customer.class

 import java.math.BigDecimal;
import java.util.Date;

public class Customer {

    private int id;
    private String name;
    private long quantity;
    private BigDecimal cost;
    private Date lastPurchasedDate;

    public Customer(int id, String name, long quantity, BigDecimal cost) {
        this.id = id;
        this.name = name;
        this.quantity = quantity;
        this.cost = cost;
    }

    // setters amp; getters are omitted for brevity.
}
  

Main.class

 import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

public class Main {

    public static void main(String[] args) {
        List<Customer> customers = Arrays.asList(new Customer(1, "A", 10, BigDecimal.valueOf(673.89)),new Customer(2, "B", 10, BigDecimal.valueOf(673.89)));
        getCustomer(customers).ifPresent(c -> System.out.println(c.getId()));
    }

    private static Optional<Customer> getCustomer(List<Customer> customers) {
        // @formatter:off
        return customers.stream()
                .max(
                        Comparator.comparing(Customer::getQuantity)
                        .thenComparing(Customer::getCost)
                         // here I need to check, If multiple customers are after 
                         // comparing the cost, I have to update the lastPurchasedDate l
                         // attribute value amp; then sort it
                        .thenComparing(Customer::getLastPurchasedDate)
                        );
        // @formatter:on
    }
}
  

Если после сортировки по стоимости доступно несколько клиентов, то мне нужно заполнить значение атрибута lastPurchasedDate, а затем отсортировать его по lastPurchasedDate.

Почему я не заполняю данные lastPurchasedDate раньше?

Чтобы получить эту информацию, мне нужно выполнить запрос в базе данных (чтобы получить информацию, мы собираемся использовать таблицу, в которой будут миллионы записей). Итак, это ограничение производительности, и я хочу этого избежать. Требуется очень редкий сценарий сравнения по lastPurchasedDate. Поэтому я не хочу без необходимости запускать этот запрос для всех клиентов.

Комментарии:

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

2. Что вы имеете в виду, говоря «затем отсортируйте это»? Вы не сортируете поток, вы извлекаете из него максимального клиента. Наличие функции, которая удаляет одного клиента из списка, а также сортирует его при некоторых условиях, является нарушением принципа единой ответственности для методов.

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

4. Сначала решите, чего вы действительно хотите, сортировки или получения максимального элемента.

5. @ErwinBolwidt, я считаю, что нам нужно сортировать данные только «при некоторых условиях». Здесь моя функция получит максимального клиента, применив некоторые условия. Как и в случае с первым, мы применим условие количества, если у нескольких клиентов максимальное количество клиентов, затем применим условие стоимости. Мой вопрос касается одного из этих данных, в данном примере заполнение lastPurchasedDate — сложная операция, и я не хочу делать это до тех пор, пока в этом нет необходимости.

Ответ №1:

Это решение, к которому я пришел…

 import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Optional;

public class Main {

    public static void main(String[] args) {
        List<Customer> customers = Arrays.asList(new Customer(1, "A", 10, BigDecimal.valueOf(673.89)),new Customer(2, "B", 10, BigDecimal.valueOf(673.89)));
        getCustomer(customers).ifPresent(c -> System.out.println(c.getId()));
    }

    private static Optional<Customer> getCustomer(List<Customer> customers) {
        // @formatter:off
        return customers.stream()
                .max(
                        Comparator.comparing(Customer::getQuantity)
                        .thenComparing(Customer::getCost)
                        .thenComparing(Main::updateLastPurchasedDate)
                        );
        // @formatter:on
    }

    private static Date updateLastPurchasedDate(Customer c) {
        Date lastPurchasedDate = customerRepository.getLastPurchasedDateById(c.getId());
        if(lastPurchasedDate == null) {
            return new Date(10000);
        }
        return lastPurchasedDate;
    }
}