【问题标题】:Java 8 : How to have a condition check in-between multiple comparisonsJava 8:如何在多重比较之间进行条件检查
【发布时间】:2019-03-25 07:29:28
【问题描述】:

我需要对具有多个条件的集合进行排序。但是,在这些条件之间,我需要修改流数据。

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 & 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 & then sort it
                        .thenComparing(Customer::getLastPurchasedDate)
                        );
        // @formatter:on
    }
}

如果按成本排序后有多个可用客户,那么我需要填充 lastPurchasedDate 属性值,然后按 lastPurchasedDate 对其进行排序。

为什么我之前没有填充 lastPurchasedDate 数据?

要获取该信息,我需要在 db 上运行一个查询(要获取信息,我们将使用一个包含数百万条记录的表)。所以这是一个性能限制,我想避免它。需要按lastPurchasedDate 进行比较的非常罕见的场景。所以我不想为所有客户不必要地运行这个查询。

【问题讨论】:

  • 我需要填充 lastPurchasedDate 属性值,然后按 lastPurchasedDate 对其进行排序。 将其作为流的中间操作也不是一个好主意。你也可以给自己写一个自定义的Comparator
  • “然后排序”是什么意思?您没有对流进行排序,而是从中取出了最大客户。在某些情况下,将单个客户从列表中取出的函数也会对其进行排序,这违反了方法的单一责任原则。
  • 我会在两个或三个流操作中完成。首先选择成本最高的那些到一个单独的列表中。如果多于一个,则修改并使用新的流操作进行最终排序。
  • 首先,决定你真正想要什么,排序或获取最大元素。
  • @ErwinBolwidt,我相信我们只需要“在某些条件下”对数据进行排序。在这里,我的函数将通过应用一些条件来获得最大客户。像首先我们将应用数量条件,如果多个客户拥有最大客户,则应用成本条件。我的问题是其中一个数据,在给定的示例中填充 lastPurchasedDate 是一项繁重的操作,除非有必要,否则我不想这样做。

标签: java lambda java-8 java-stream


【解决方案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;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    • 1970-01-01
    相关资源
    最近更新 更多