- 排序实现
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
class Customer {
private int id;
private LocalDate registrationDate;
private BigDecimal purchaseAmount;
public Customer(int id, LocalDate registrationDate, BigDecimal purchaseAmount) {
this.id = id;
this.registrationDate = registrationDate;
this.purchaseAmount = purchaseAmount;
}
public int getId() {
return id;
}
public LocalDate getRegistrationDate() {
return registrationDate;
}
public BigDecimal getPurchaseAmount() {
return purchaseAmount;
}
}
public class Main {
public static void main(String[] args) {
List<Customer> customers = List.of(
new Customer(1, LocalDate.of(2023, 1, 1), new BigDecimal("100")),
new Customer(2, LocalDate.of(2023, 2, 1), new BigDecimal("50")),
new Customer(3, LocalDate.of(2023, 1, 1), new BigDecimal("150"))
);
List<Customer> sortedCustomers = customers.stream()
.sorted(Comparator.comparing(Customer::getRegistrationDate).reversed()
.thenComparing(Customer::getPurchaseAmount))
.collect(Collectors.toList());
sortedCustomers.forEach(customer -> System.out.println(
"Id: " + customer.getId() +
", Registration Date: " + customer.getRegistrationDate() +
", Purchase Amount: " + customer.getPurchaseAmount()
));
}
}
- 性能优化思路
- 减少比较次数:
- 提前过滤:在排序前,根据一些已知条件过滤掉不需要参与排序的数据。例如,如果已知大部分数据的
registrationDate
在某个时间段之后,可以先过滤掉不符合该时间段的数据。
- 使用部分排序:如果只需要获取前
n
个排序后的元素,可以使用limit
方法。Java Stream在这种情况下可能会采用更优化的策略,避免对整个数据集进行完全排序。
- 选择合适的数据结构:
- 并行流:对于大数据量,可以考虑使用并行流
parallelStream()
。在多核CPU环境下,并行流能够利用多个线程并行处理数据,加快排序速度。但要注意,并行流存在线程安全和数据一致性问题,确保Customer
对象的属性访问是线程安全的。
- 外部排序:当数据量过大,内存无法容纳时,可以考虑外部排序算法。外部排序通常将数据分成多个部分,分别在内存中排序,然后再合并这些有序的部分。Java中可以通过
java.util.PriorityQueue
结合文件操作实现简单的外部排序。
- 优化比较器:
- 缓存比较结果:如果
Customer
对象的属性计算比较复杂,例如registrationDate
或purchaseAmount
需要经过复杂计算得到,可以考虑缓存这些属性值,避免每次比较都重新计算。
- 关键代码片段 - 并行流优化
List<Customer> sortedCustomers = customers.parallelStream()
.sorted(Comparator.comparing(Customer::getRegistrationDate).reversed()
.thenComparing(Customer::getPurchaseAmount))
.collect(Collectors.toList());
- 关键代码片段 - 外部排序示例(简化版)
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Comparator;
import java.util.PriorityQueue;
class ExternalSortCustomer {
private int id;
private LocalDate registrationDate;
private BigDecimal purchaseAmount;
public ExternalSortCustomer(int id, LocalDate registrationDate, BigDecimal purchaseAmount) {
this.id = id;
this.registrationDate = registrationDate;
this.purchaseAmount = purchaseAmount;
}
public int getId() {
return id;
}
public LocalDate getRegistrationDate() {
return registrationDate;
}
public BigDecimal getPurchaseAmount() {
return purchaseAmount;
}
@Override
public String toString() {
return "Id: " + id +
", Registration Date: " + registrationDate +
", Purchase Amount: " + purchaseAmount;
}
}
public class ExternalSortExample {
public static void main(String[] args) throws IOException {
// 模拟大数据量,这里只简单举例
PriorityQueue<ExternalSortCustomer> pq = new PriorityQueue<>(Comparator.comparing(ExternalSortCustomer::getRegistrationDate).reversed()
.thenComparing(ExternalSortCustomer::getPurchaseAmount));
pq.add(new ExternalSortCustomer(1, LocalDate.of(2023, 1, 1), new BigDecimal("100")));
pq.add(new ExternalSortCustomer(2, LocalDate.of(2023, 2, 1), new BigDecimal("50")));
pq.add(new ExternalSortCustomer(3, LocalDate.of(2023, 1, 1), new BigDecimal("150")));
try (BufferedWriter writer = new BufferedWriter(new FileWriter("sorted_customers.txt"))) {
while (!pq.isEmpty()) {
writer.write(pq.poll().toString() + "\n");
}
}
}
}