我有一个Invoice对象列表,其中包含属性频率和数量(BigDecimal)。
1)需要在不考虑精度的情况下,根据频率乘以和改变量。在下面显示的代码中输出但是输出失去了一些精度。金额值应为100。
2)是否可以使用java 8 stream API替换发票列表中的金额值。 尝试使用
.Designer.cs
但这不会替换对象中的金额值。 在这种情况下无法弄清楚使用replaceAll,尝试下面的代码,但是给出了编译错误,
invoiceList.forEach(s -> s.getAmount().multiply(new BigDecimal("10")));
整个主要课程如下。无法更改任何数据类型或设计。我必须从Web服务处理获取的列表。
newList.replaceAll((v) -> v.getAmount().multiply(frequencyFactor.get(v.getFrequency())));
OUTPUT是:
public class InvoiceMain {
public static void main(String[] args) {
List<Invoice> invoiceList = Arrays.asList(new Invoice("Quarterly", new BigDecimal(300)), new Invoice("Annually", new BigDecimal(1200)));
Map<String, BigDecimal> frequencyFactor = new HashMap<>();
frequencyFactor.put("Annually", new BigDecimal(1.0 / 12));
frequencyFactor.put("Quarterly", new BigDecimal(1.0 / 3));
for (Invoice invoice : invoiceList) {
invoice.setAmount(invoice.getAmount().multiply(frequencyFactor.get(invoice.getFrequency())));
}
System.out.println(invoiceList);
}
}
class Invoice {
private String frequency;
private BigDecimal amount;
public Invoice(String frequency, BigDecimal amount) {
super();
this.frequency = frequency;
this.amount = amount;
}
public String getFrequency() {
return frequency;
}
public void setFrequency(String frequency) {
this.frequency = frequency;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
@Override
public String toString() {
return "Invoice [frequency=" + frequency + ", amount=" + amount + "]";
}
}
必需的输出是
[Invoice [frequency=Quarterly, amount=99.999..], Invoice [frequency=Annually, amount=99.999...]]
答案 0 :(得分:6)
缺陷是使用带有double的BigDecimal构造函数。然后BigDecimal无法确定精度并使用一个适合double的精度,也会引入一个inprecise值(来自double)。
new BigDecimal(1.0/12)
使用divideBy
将最佳状态更改为12:使用Map<String, BigDecimal> divisors = ...
divisors.put("Anually", BigDecimal.valueOf(12));
...
final Map<String, BigDecimal> finalDivisors = divisors;
BigDecimal sum = invoiceList.stream()
.map(inv -> inv.amount.divideBy(finalDivisors.get(inv.frequency))
.sum();
。
static class Invoice {
final BigDecimal amount;
final int months;
Invoice(BigDecimal amount, int months) {
this.amount = amount;
this.months = months;
}
}
public static void main(String[] args) {
List<Invoice> invoices = Arrays.asList(
new Invoice(new BigDecimal("12.50"), 3),
new Invoice(new BigDecimal("120.50"), 12),
new Invoice(new BigDecimal("7.25"), 3));
BigDecimal sum = invoices.stream()
.map(inv -> inv.amount.divide(BigDecimal.valueOf(inv.months),
RoundingMode.HALF_UP))
.reduce(BigDecimal.ZERO, BigDecimal::add);
System.out.println("Sum: " + sum); // 16.63
}
在实际代码中:
{{1}}
答案 1 :(得分:4)
使用枚举的替代解决方案。
public enum Frequency {
ANUALLY(12), QUARTERLY(3);
private final int divideBy;
Frequency(final int div) { this.divideBy = div; }
public int getDivideBy() { return this.divideBy; }
}
public class InvoiceMain {
public static void main(String[] args) {
List<Invoice> invoiceList = Arrays.asList(new Invoice(Frequency.QUARTERLY,new BigDecimal(300)), new Invoice(Frequency.ANUALLY, new BigDecimal(1200)));
for(Invoice invoice: invoiceList) {
invoice.setAmount(invoice.getAmount().divide(invoice.getFrequency().getDivideBy())));
}
System.out.println(invoiceList);
}
}
class Invoice {
private Frequency frequency;
private BigDecimal amount;
public Invoice(Frequency frequency, BigDecimal amount) {
super();
this.frequency = frequency;
this.amount = amount;
}
public Frequency getFrequency() {
return frequency;
}
public void setFrequency(Frequency frequency) {
this.frequency = frequency;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
@Override
public String toString() {
return "Invoice [frequency=" + frequency + ", amount=" + amount + "]";
}
}
答案 2 :(得分:1)
您好我不确定您是否已经解决了问题,但如果您使用Double而不是BigDezimal,我会得到正确的输出,我试着这样:
public class InvoiceMain {
public static void main(String[] args) {
List<Invoice> invoiceList = Arrays.asList(new
Invoice("Quarterly",300.0),new Invoice("Annually", 1200.0));
Map<String, Double> frequencyFactor = new HashMap<>();
frequencyFactor.put("Annually", (Double)(1.0 / 12));
frequencyFactor.put("Quarterly",(Double)(1.0 / 3));
for (Invoice invoice : invoiceList) {
switch (invoice.getFrequency()) {
case "Quarterly": // divide by 4, to convert to Monthly
invoice.setAmount(invoice.getAmount() *
(frequencyFactor.get(invoice.getFrequency())));
break;
case "Annually": // divide by 12, to convert to Monthly
invoice.setAmount(invoice.getAmount() *
(frequencyFactor.get(invoice.getFrequency())));
break;
}
}
System.out.println(invoiceList);
}
}
class Invoice {
private String frequency;
private Double amount;
public Invoice(String frequency, Double amount) {
super();
this.frequency = frequency;
this.amount = amount;
}
public String getFrequency() {
return frequency;
}
public void setFrequency(String frequency) {
this.frequency = frequency;
}
public double getAmount() {
return amount;
}
public void setAmount(Double amount) {
this.amount = amount;
}
@Override
public String toString() {
return "Invoice [frequency=" + frequency + ", amount=" + amount + "]";
}
}
以下是输出:
[发票[频率=季度,金额= 100.0],发票[频率=每年,金额= 100.0]]
干杯,
凯博
答案 3 :(得分:1)
在阅读其他答案后,我发现您真正想要的是计算每月 Invoice
,您可以引入Value Object Invoice
&amp;枚举Frequency
在这里根据OO方式制作代码并且更简单:
enum Frequency {
ANUALLY(12), QUARTERLY(3), MONTHLY(1);
private final int months;
Frequency(final int months) {
this.months = months;
}
private BigDecimal monthly(BigDecimal amount) {
return amount.divide(BigDecimal.valueOf(months));
}
}
class Invoice {
private Frequency frequency;
private BigDecimal amount;
public Invoice(Frequency frequency, BigDecimal amount) {
this.frequency = frequency;
this.amount = amount;
}
private Invoice monthly() {
return new Invoice(Frequency.MONTHLY, frequency.monthly(this.amount));
}
// getters are ignored here
@Override
public String toString() {
return "Invoice [frequency=" + frequency + ", amount=" + amount + "]";
}
}
那么您的主要课程可以使用如下的流API:
class InvoiceMain {
public static void main(String[] args) {
List<Invoice> invoiceList = Arrays.asList(
new Invoice(Frequency.QUARTERLY, new BigDecimal(300)),
new Invoice(Frequency.ANUALLY, new BigDecimal(1200))
);
System.out.println(invoiceList.stream().map(Invoice::monthly)
.collect(Collectors.toList()));
}
}
[
Invoice [frequency=MONTHLY, amount=100],
Invoice [frequency=MONTHLY, amount=100]
]
答案 4 :(得分:0)
阅读完回复后,我修改了频率因子值,并将乘法乘以除以。
Map<String,BigDecimal> frequencyFactor = new HashMap<>();
frequencyFactor.put("Monthly", BigDecimal.valueOf(1));
frequencyFactor.put("Annually",BigDecimal.valueOf(12));
frequencyFactor.put("Yearly", BigDecimal.valueOf(12));
frequencyFactor.put("Quaterly", BigDecimal.valueOf(3));
frequencyFactor.put("Semiannually", BigDecimal.valueOf(6));
for (Subscription invoice : newList) {
invoice.setAmount(invoice.getAmount().divide(frequencyFactor.get(invoice.getFrequency()),2,RoundingMode.HALF_UP));
}
newList.forEach(s-> System.out.println(s));