java currencyamount_Java 9中新的货币API

MonetaryAmount的使用

可以在MonetaryAmount上进行算术运算:

MonetaryAmount twelveEuro = fiveEuro.add(sevenEuro); // "EUR 12"

MonetaryAmount twoEuro = sevenEuro.subtract(fiveEuro); // "EUR 2"

MonetaryAmount sevenPointFiveEuro = fiveEuro.multiply(1.5); // "EUR 7.5"

// MonetaryAmount can have a negative NumberValue

MonetaryAmount minusTwoEuro = fiveEuro.subtract(sevenEuro); // "EUR -2"

// some useful utility methods

boolean greaterThan = sevenEuro.isGreaterThan(fiveEuro); // true

boolean positive = sevenEuro.isPositive(); // true

boolean zero = sevenEuro.isZero(); // false

// Note that MonetaryAmounts need to have the same CurrencyUnit to do mathematical operations

// this fails with: javax.money.MonetaryException: Currency mismatch: EUR/USD

fiveEuro.add(tenUsDollar);

舍入操作是金额换算里面非常重要的一部分。MonetaryAmount可以使用舍入操作符来进行四舍五入:

CurrencyUnit usd = MonetaryCurrencies.getCurrency("USD");

MonetaryAmount dollars = Money.of(12.34567, usd);

MonetaryOperator roundingOperator = MonetaryRoundings.getRounding(usd);

MonetaryAmount roundedDollars = dollars.with(roundingOperator); // USD 12.35

这里12.3456美金就会按当前货币默认的舍入规则来进行换算。

在操作MonetaryAmount集合时,有许多实用的工具方法可以用来进行过滤,排序以及分组。这些方法还可以与Java 8的流API一起配套使用。

看一下下面这个集合:

List amounts = new ArrayList<>();

amounts.add(Money.of(2, "EUR"));

amounts.add(Money.of(42, "USD"));

amounts.add(Money.of(7, "USD"));

amounts.add(Money.of(13.37, "JPY"));

amounts.add(Money.of(18, "USD"));

我们可以根据CurrencyUnit来进行金额过滤:

CurrencyUnit yen = MonetaryCurrencies.getCurrency("JPY");

CurrencyUnit dollar = MonetaryCurrencies.getCurrency("USD");

// 根据货币过滤,只返回美金

// result is [USD 18, USD 7, USD 42]

List onlyDollar = amounts.stream()

.filter(MonetaryFunctions.isCurrency(dollar))

.collect(Collectors.toList());

// 根据货币过滤,只返回美金和日元

// [USD 18, USD 7, JPY 13.37, USD 42]

List onlyDollarAndYen = amounts.stream()

.filter(MonetaryFunctions.isCurrency(dollar, yen))

.collect(Collectors.toList());

我们还可以过滤出大于或小于某个阈值的金额:

MonetaryAmount tenDollar = Money.of(10, dollar);

// [USD 42, USD 18]

List greaterThanTenDollar = amounts.stream()

.filter(MonetaryFunctions.isCurrency(dollar))

.filter(MonetaryFunctions.isGreaterThan(tenDollar))

.collect(Collectors.toList());

排序也是类似的:

// Sorting dollar values by number value

// [USD 7, USD 18, USD 42]

List sortedByAmount = onlyDollar.stream()

.sorted(MonetaryFunctions.sortNumber())

.collect(Collectors.toList());

// Sorting by CurrencyUnit

// [EUR 2, JPY 13.37, USD 42, USD 7, USD 18]

List sortedByCurrencyUnit = amounts.stream()

.sorted(MonetaryFunctions.sortCurrencyUnit())

.collect(Collectors.toList());

还有分组操作:

// 按货币单位进行分组

// {USD=[USD 42, USD 7, USD 18], EUR=[EUR 2], JPY=[JPY 13.37]}

Map> groupedByCurrency = amounts.stream()

.collect(MonetaryFunctions.groupByCurrencyUnit());

// 分组并进行汇总

Map summary = amounts.stream()

.collect(MonetaryFunctions.groupBySummarizingMonetary()).get();

// get summary for CurrencyUnit USD

MonetarySummaryStatistics dollarSummary = summary.get(dollar);

MonetaryAmount average = dollarSummary.getAverage(); // "USD 22.333333333333333333.."

MonetaryAmount min = dollarSummary.getMin(); // "USD 7"

MonetaryAmount max = dollarSummary.getMax(); // "USD 42"

MonetaryAmount sum = dollarSummary.getSum(); // "USD 67"

long count = dollarSummary.getCount(); // 3

MonetaryFunctions还提供了归约函数,可以用来获取最大值,最小值,以及求和:

List amounts = new ArrayList<>();

amounts.add(Money.of(10, "EUR"));

amounts.add(Money.of(7.5, "EUR"));

amounts.add(Money.of(12, "EUR"));

Optional max = amounts.stream().reduce(MonetaryFunctions.max()); // "EUR 7.5"

Optional min = amounts.stream().reduce(MonetaryFunctions.min()); // "EUR 12"

Optional sum = amounts.stream().reduce(MonetaryFunctions.sum()); // "EUR 29.5"

自定义的MonetaryAmount操作

MonetaryAmount还提供了一个非常友好的扩展点叫作MonetaryOperator。MonetaryOperator是一个函数式接口,它接收一个MonetaryAmount入参并返回一个新的MonetaryAmount对象。

// A monetary operator that returns 10% of the input MonetaryAmount

// Implemented using Java 8 Lambdas

MonetaryOperator tenPercentOperator = (MonetaryAmount amount) -> {

BigDecimal baseAmount = amount.getNumber().numberValue(BigDecimal.class);

BigDecimal tenPercent = baseAmount.multiply(new BigDecimal("0.1"));

return Money.of(tenPercent, amount.getCurrency());

};

MonetaryAmount dollars = Money.of(12.34567, "USD");

// apply tenPercentOperator to MonetaryAmount

MonetaryAmount tenPercentDollars = dollars.with(tenPercentOperator); // USD 1.234567

标准的API特性都是通过MonetaryOperator的接口来实现的。比方说,前面看到的舍入操作就是以MonetaryOperator接口的形式来提供的。

汇率

货币兑换率可以通过ExchangeRateProvider来获取。JavaMoney自带了多个不同的ExchangeRateProvider的实现。其中最重要的两个是ECBCurrentRateProvider与 IMFRateProvider。

ECBCurrentRateProvider查询的是欧洲中央银行(European Central Bank,ECB)的数据而IMFRateProvider查询的是国际货币基金组织(International Monetary Fund,IMF)的汇率。

// get the default ExchangeRateProvider (CompoundRateProvider)

ExchangeRateProvider exchangeRateProvider = MonetaryConversions.getExchangeRateProvider();

// get the names of the default provider chain

// [IDENT, ECB, IMF, ECB-HIST]

List defaultProviderChain = MonetaryConversions.getDefaultProviderChain();

// get a specific ExchangeRateProvider (here ECB)

ExchangeRateProvider ecbExchangeRateProvider = MonetaryConversions.getExchangeRateProvider("ECB");

如果没有指定ExchangeRateProvider的话返回的就是CompoundRateProvider。 CompoundRateProvider会将汇率转换请求委派给一个ExchangeRateProvider链并将第一个返回准确结果的提供商的数据 返回。

// get the exchange rate from euro to us dollar

ExchangeRate rate = exchangeRateProvider.getExchangeRate("EUR", "USD");

NumberValue factor = rate.getFactor(); // 1.2537 (at time writing)

CurrencyUnit baseCurrency = rate.getBaseCurrency(); // EUR

CurrencyUnit targetCurrency = rate.getCurrency(); // USD

货币转换

不同货币间的转换可以通过ExchangeRateProvider返回的CurrencyConversions来完成。

// get the CurrencyConversion from the default provider chain

CurrencyConversion dollarConversion = MonetaryConversions.getConversion("USD");

// get the CurrencyConversion from a specific provider

CurrencyConversion ecbDollarConversion = ecbExchangeRateProvider.getCurrencyConversion("USD");

MonetaryAmount tenEuro = Money.of(10, "EUR");

// convert 10 euro to us dollar

MonetaryAmount inDollar = tenEuro.with(dollarConversion); // "USD 12.537" (at the time writing)

请注意CurrencyConversion也实现了MonetaryOperator接口。正如其它操作一样,它也能通过MonetaryAmount.with()方法来调用。

格式化及解析

MonetaryAmount可以通过MonetaryAmountFormat来与字符串进行解析/格式化。

// formatting by locale specific formats

MonetaryAmountFormat germanFormat = MonetaryFormats.getAmountFormat(Locale.GERMANY);

MonetaryAmountFormat usFormat = MonetaryFormats.getAmountFormat(Locale.CANADA);

MonetaryAmount amount = Money.of(12345.67, "USD");

String usFormatted = usFormat.format(amount); // "USD12,345.67"

String germanFormatted = germanFormat.format(amount); // 12.345,67 USD

// A MonetaryAmountFormat can also be used to parse MonetaryAmounts from strings

MonetaryAmount parsed = germanFormat.parse("12,4 USD");

可以通过AmountFormatQueryBuilder来生成自定义的格式。

// Creating a custom MonetaryAmountFormat

MonetaryAmountFormat customFormat = MonetaryFormats.getAmountFormat(

AmountFormatQueryBuilder.of(Locale.US)

.set(CurrencyStyle.NAME)

.set("pattern", "00,00,00,00.00 ¤")

.build());

// results in "00,01,23,45.67 US Dollar"

String formatted = customFormat.format(amount);

注意,这里的¤符号在模式串中是作为货币的占位符。

总结

新的货币API这里已经介绍得差不多了。并且目前它的实现也已经相对稳定了(但还需要多补充些文档)。期待能在Java 9中看到这套新的接口!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值