gpt4 book ai didi

java - 这是按多个属性对项目进行分组并检查另一个属性是否为 null 或不为 null 的有效方法吗?

转载 作者:行者123 更新时间:2023-12-02 08:28:07 25 4
gpt4 key购买 nike

我有以下类,它有 3 个我关心的属性:

public class Invoice {
private String invoiceNumber;
private String vendorCode;
private BigDecimal vatAmount;
}

我需要按 invoiceNumbervendorCode 对它们进行分组,并检查对于所有这些分组的项目,vatAmount 对于所有项目都为 null条目或不为空。如果任一条件失败,我都会抛出一个已检查异常 (RuleException)。到目前为止我有这个:

List<Invoice> invoices = ....;

Map<List<String>, List<Invoice>> uniqueInvoiceNumbers = invoices.stream()
.collect(Collectors.groupingBy(e-> Arrays.asList(e.getInvoiceNumber(), e.getVendorCode())));

for (Map.Entry<List<String>, List<Invoice>> entrySet : uniqueInvoiceNumbers.entrySet()) {
boolean allNull = entrySet.getValue().stream().allMatch(e-> e.getVatAmount() == null);
boolean allFilled = entrySet.getValue().stream().allMatch(e-> e.getVatAmount() != null);
if (!allNull && !allFilled) {
throw new RuleException("The invoices associated with " + entrySet.getKey().get(0) + " and vendor " + entrySet.getKey().get(1) + " have had their vat amount partially filled. They should either all be filled in or none at all");
}
}

完成检查后,我会丢弃分组的项目uniqueInvoiceNumbers,因为它们仅用于检查。

有更好的方法吗?发票集合的大小范围为 1 到 200 项。

<小时/>

我用过this answer让代码按两个不同的键进行分组。

最佳答案

您只需要一次检查,因为“全部为空”或“全部非空”就是为了找到矛盾的元素。因此,列表至少需要两个元素才能包含矛盾的元素。当您检查 null 的第一个元素时,你知道,是否所有其他元素都必须是 null或非null .

Optional<List<String>> o = uniqueInvoiceNumbers.entrySet()
.filter(e -> e.getValue().size() > 1)
.filter(e -> {
boolean isNull = e.getValue().get(0).getVatAmount() == null;
return e.getValue().stream().map(Invoice::getVatAmount)
.anyMatch(isNull? Objects::nonNull: Objects::isNull);
})
.map(Map.Entry::getKey)
.findAny();

if(o.isPresent()) { // can't use ifPresent with checked exception
List<String> key = o.get();
throw new RuleException("The invoices associated with "
+ key.get(0) + " and vendor " + key.get(1)
+ " have had their vat amount partially filled."
+ " They should either all be filled in or none at all");
}

您可以内联上面代码中使用的一些变量,这将使代码更简洁,但不一定更具可读性。

<小时/>

如果您不需要Map<List<String>, List<Invoice>> ,但仅收集它以进行此检查,您可以在分组时在一个操作中执行检查,但是,由于检查的异常,我将其实现为循环:

List<Invoice> invoices = ....;

Map<List<String>, Boolean> uniqueInvoiceNumbers = new HashMap<>();
for(Invoice i : invoices) {
List<String> key = Arrays.asList(i.getInvoiceNumber(), i.getVendorCode());
boolean isNull = i.getVatAmount() == null;
Boolean existing = uniqueInvoiceNumbers.putIfAbsent(key, isNull);
if(existing != null && existing != isNull) {
throw new RuleException("The invoices associated with "
+ key.get(0) + " and vendor " + key.get(1)
+ " have had their vat amount partially filled."
+ " They should either all be filled in or none at all");
}
}

如果RuleException是一个未经检查的异常,我们可以这样做:

invoices.stream()
.collect(Collectors.toMap(
i -> Arrays.asList(i.getInvoiceNumber(), i.getVendorCode()),
Function.identity(),
(i1,i2) -> {
if((i1.getVatAmount() == null) != (i2.getVatAmount() == null)) {
throw new RuleException("The invoices associated with "
+ i.getInvoiceNumber() + " and vendor " + i.getVendorCode()
+ " have had their vat amount partially filled."
+ " They should either all be filled in or none at all");
}
return i1;
}));

这是相同的逻辑,尽管我们不能只映射到 Boolean value,这样,合并函数就不会知道异常消息的键。而且,如上所述,它需要取消检查异常,或者必须将其包装到另一个异常中,以便在流操作之外提取。这使得循环变体更可取,除非并行处理发挥作用,我不会考虑 200 个元素......

关于java - 这是按多个属性对项目进行分组并检查另一个属性是否为 null 或不为 null 的有效方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59190592/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com