国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Java 9中新的貨幣API

瀏覽:10日期:2022-09-06 11:10:07

JSR 354定義了一套新的Java貨幣API,計(jì)劃會(huì)在Java 9中正式引入。本文中我們將來(lái)看一下它的參考實(shí)現(xiàn):JavaMoney的當(dāng)前進(jìn)展。

正如我在之前那篇Java 8新的日期時(shí)間API一文中那樣,本文主要也是通過(guò)一些代碼來(lái)演示下新的API的用法 。

在開(kāi)始之前,我想先用一段話來(lái)簡(jiǎn)短地總結(jié)一下規(guī)范定義的這套新的API的用意何在:

對(duì)許多應(yīng)用而言貨幣價(jià)值都是一個(gè)關(guān)鍵的特性,但JDK對(duì)此卻幾乎沒(méi)有任何支持。嚴(yán)格來(lái)講,現(xiàn)有的java.util.Currency類只是代表了當(dāng)前ISO 4217貨幣的一個(gè)數(shù)據(jù)結(jié)構(gòu),但并沒(méi)有關(guān)聯(lián)的值或者自定義貨幣。JDK對(duì)貨幣的運(yùn)算及轉(zhuǎn)換也沒(méi)有內(nèi)建的支持,更別說(shuō)有一個(gè)能夠代表貨幣值的標(biāo)準(zhǔn)類型了。

如果你用的是Maven的話,只需把下面的引用添加到工里面便能夠體驗(yàn)下該參考實(shí)現(xiàn)的當(dāng)前功能了:

<dependency> <groupId>org.javamoney</groupId> <artifactId>moneta</artifactId> <version>0.9</version></dependency>

規(guī)范中提到的類及接口都在javax.money.*包下面。

我們先從核心的兩個(gè)接口CurrencyUnit與MonetaryAmount開(kāi)始講起。

CurrencyUnit及MonetaryAmount

CurrencyUnit代表的是貨幣。它有點(diǎn)類似于現(xiàn)在的java.util.Currency類,不同之處在于它支持自定義的實(shí)現(xiàn)。從規(guī)范的定義來(lái)看,java.util.Currency也是可以實(shí)現(xiàn)該接口的。CurrencyUnit的實(shí)例可以通過(guò)MonetaryCurrencies工廠來(lái)獲取:

// 根據(jù)貨幣代碼來(lái)獲取貨幣單位 CurrencyUnit euro = MonetaryCurrencies.getCurrency("EUR"); CurrencyUnit usDollar = MonetaryCurrencies.getCurrency("USD"); // 根據(jù)國(guó)家及地區(qū)來(lái)獲取貨幣單位 CurrencyUnit yen = MonetaryCurrencies.getCurrency(Locale.JAPAN); CurrencyUnit canadianDollar = MonetaryCurrencies.getCurrency(Locale.CANADA);

MontetaryAmount代表的是某種貨幣的具體金額。通常它都會(huì)與某個(gè)CurrencyUnit綁定。

MontetaryAmount和CurrencyUnit一樣,也是一個(gè)能支持多種實(shí)現(xiàn)的接口。

CurrencyUnit與MontetaryAmount的實(shí)現(xiàn)必須是不可變,線程安全且可比較的。

/ get MonetaryAmount from CurrencyUnitCurrencyUnit euro = MonetaryCurrencies.getCurrency("EUR");MonetaryAmount fiveEuro = Money.of(5, euro); // get MonetaryAmount from currency codeMonetaryAmount tenUsDollar = Money.of(10, "USD"); // FastMoney is an alternative MonetaryAmount factory that focuses on performanceMonetaryAmount sevenEuro = FastMoney.of(7, euro);

Money與FastMoney是JavaMoney庫(kù)中MonetaryAmount的兩種實(shí)現(xiàn)。Money是默認(rèn)實(shí)現(xiàn),它使用BigDecimal來(lái)存儲(chǔ)金額。FastMoney是可選的另一個(gè)實(shí)現(xiàn),它用long類型來(lái)存儲(chǔ)金額。根據(jù)文檔來(lái)看,F(xiàn)astMoney上的操作要比Money的快10到15倍左右。然而,F(xiàn)astMoney的金額大小與精度都受限于long類型。

注意了,這里的Money和FastMoney都是具體的實(shí)現(xiàn)類(它們?cè)趏rg.javamoney.moneta.*包下面,而不是javax.money.*)。如果你不希望指定具體類型的話,可以通過(guò)MonetaryAmountFactory來(lái)生成一個(gè)MonetaryAmount的實(shí)例:

MonetaryAmount specAmount = MonetaryAmounts.getDefaultAmountFactory().setNumber(123.45) .setCurrency("USD") .create();

當(dāng)且僅當(dāng)實(shí)現(xiàn)類,貨幣單位,以及數(shù)值全部相等時(shí)才認(rèn)為這兩個(gè)MontetaryAmount實(shí)例是相等的。

MonetaryAmount oneEuro = Money.of(1, MonetaryCurrencies.getCurrency("EUR"));boolean isEqual = oneEuro.equals(Money.of(1, "EUR")); // trueboolean isEqualFast = oneEuro.equals(FastMoney.of(1, "EUR")); // false

MonetaryAmount內(nèi)包含豐富的方法,可以用來(lái)獲取具體的貨幣,金額,精度等等:

MonetaryAmount monetaryAmount = Money.of(123.45, euro);CurrencyUnit currency = monetaryAmount.getCurrency();NumberValue numberValue = monetaryAmount.getNumber(); int intValue = numberValue.intValue(); // 123double doubleValue = numberValue.doubleValue(); // 123.45long fractionDenominator = numberValue.getAmountFractionDenominator(); // 100long fractionNumerator = numberValue.getAmountFractionNumerator(); // 45int precision = numberValue.getPrecision(); // 5 // NumberValue extends java.lang.Number. // So we assign numberValue to a variable of type NumberNumber number = numberValue;

MonetaryAmount的使用

可以在MonetaryAmount上進(jìn)行算術(shù)運(yùn)算:

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 NumberValueMonetaryAmount minusTwoEuro = fiveEuro.subtract(sevenEuro); // "EUR -2" // some useful utility methodsboolean greaterThan = sevenEuro.isGreaterThan(fiveEuro); // trueboolean positive = sevenEuro.isPositive(); // trueboolean 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/USDfiveEuro.add(tenUsDollar);

舍入操作是金額換算里面非常重要的一部分。MonetaryAmount可以使用舍入操作符來(lái)進(jìn)行四舍五入:

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美金就會(huì)按當(dāng)前貨幣默認(rèn)的舍入規(guī)則來(lái)進(jìn)行換算。

在操作MonetaryAmount集合時(shí),有許多實(shí)用的工具方法可以用來(lái)進(jìn)行過(guò)濾,排序以及分組。這些方法還可以與Java 8的流API一起配套使用。

看一下下面這個(gè)集合:

List<MonetaryAmount> 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"));

我們可以根據(jù)CurrencyUnit來(lái)進(jìn)行金額過(guò)濾:

CurrencyUnit yen = MonetaryCurrencies.getCurrency("JPY");CurrencyUnit dollar = MonetaryCurrencies.getCurrency("USD");// 根據(jù)貨幣過(guò)濾,只返回美金// result is [USD 18, USD 7, USD 42]List<MonetaryAmount> onlyDollar = amounts.stream() .filter(MonetaryFunctions.isCurrency(dollar)) .collect(Collectors.toList()); // 根據(jù)貨幣過(guò)濾,只返回美金和日元// [USD 18, USD 7, JPY 13.37, USD 42]List<MonetaryAmount> onlyDollarAndYen = amounts.stream() .filter(MonetaryFunctions.isCurrency(dollar, yen)) .collect(Collectors.toList());

我們還可以過(guò)濾出大于或小于某個(gè)閾值的金額:

MonetaryAmount tenDollar = Money.of(10, dollar); // [USD 42, USD 18]List<MonetaryAmount> 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<MonetaryAmount> sortedByAmount = onlyDollar.stream() .sorted(MonetaryFunctions.sortNumber()) .collect(Collectors.toList()); // Sorting by CurrencyUnit// [EUR 2, JPY 13.37, USD 42, USD 7, USD 18]List<MonetaryAmount> sortedByCurrencyUnit = amounts.stream() .sorted(MonetaryFunctions.sortCurrencyUnit()) .collect(Collectors.toList());

還有分組操作:

// 按貨幣單位進(jìn)行分組// {USD=[USD 42, USD 7, USD 18], EUR=[EUR 2], JPY=[JPY 13.37]}Map<CurrencyUnit, List<MonetaryAmount>> groupedByCurrency = amounts.stream() .collect(MonetaryFunctions.groupByCurrencyUnit()); // 分組并進(jìn)行匯總Map<CurrencyUnit, MonetarySummaryStatistics> summary = amounts.stream() .collect(MonetaryFunctions.groupBySummarizingMonetary()).get(); // get summary for CurrencyUnit USDMonetarySummaryStatistics 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還提供了歸約函數(shù),可以用來(lái)獲取最大值,最小值,以及求和:

List<MonetaryAmount> amounts = new ArrayList<>();amounts.add(Money.of(10, "EUR"));amounts.add(Money.of(7.5, "EUR"));amounts.add(Money.of(12, "EUR")); Optional<MonetaryAmount> max = amounts.stream().reduce(MonetaryFunctions.max()); // "EUR 7.5"Optional<MonetaryAmount> min = amounts.stream().reduce(MonetaryFunctions.min()); // "EUR 12"Optional<MonetaryAmount> sum = amounts.stream().reduce(MonetaryFunctions.sum()); //

自定義的MonetaryAmount操作

MonetaryAmount還提供了一個(gè)非常友好的擴(kuò)展點(diǎn)叫作MonetaryOperator。MonetaryOperator是一個(gè)函數(shù)式接口,它接收一個(gè)MonetaryAmount入?yún)⒉⒎祷匾粋€(gè)新的MonetaryAmount對(duì)象。

// A monetary operator that returns 10% of the input MonetaryAmount// Implemented using Java 8 LambdasMonetaryOperator 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 MonetaryAmountMonetaryAmount tenPercentDollars = dollars.with(tenPercentOperator); // USD 1.234567

標(biāo)準(zhǔn)的API特性都是通過(guò)MonetaryOperator的接口來(lái)實(shí)現(xiàn)的。比方說(shuō),前面看到的舍入操作就是以MonetaryOperator接口的形式來(lái)提供的。

匯率

貨幣兌換率可以通過(guò)ExchangeRateProvider來(lái)獲取。JavaMoney自帶了多個(gè)不同的ExchangeRateProvider的實(shí)現(xiàn)。其中最重要的兩個(gè)是ECBCurrentRateProvider與 IMFRateProvider。

ECBCurrentRateProvider查詢的是歐洲中央銀行(European Central Bank,ECB)的數(shù)據(jù)而IMFRateProvider查詢的是國(guó)際貨幣基金組織(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<String> defaultProviderChain = MonetaryConversions.getDefaultProviderChain(); // get a specific ExchangeRateProvider (here ECB)ExchangeRateProvider ecbExchangeRateProvider = MonetaryConversions.getExchangeRateProvider("ECB");

如果沒(méi)有指定ExchangeRateProvider的話返回的就是CompoundRateProvider。CompoundRateProvider會(huì)將匯率轉(zhuǎn)換請(qǐng)求委派給一個(gè)ExchangeRateProvider鏈并將第一個(gè)返回準(zhǔn)確結(jié)果的提供商的數(shù)據(jù)返回。

// get the exchange rate from euro to us dollarExchangeRate rate = exchangeRateProvider.getExchangeRate("EUR", "USD"); NumberValue factor = rate.getFactor(); // 1.2537 (at time writing)CurrencyUnit baseCurrency = rate.getBaseCurrency(); // EURCurrencyUnit targetCurrency = rate.getCurrency(); // USD

貨幣轉(zhuǎn)換

不同貨幣間的轉(zhuǎn)換可以通過(guò)ExchangeRateProvider返回的CurrencyConversions來(lái)完成。

// get the CurrencyConversion from the default provider chainCurrencyConversion dollarConversion = MonetaryConversions.getConversion("USD"); // get the CurrencyConversion from a specific providerCurrencyConversion 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)

請(qǐng)注意CurrencyConversion也實(shí)現(xiàn)了MonetaryOperator接口。正如其它操作一樣,它也能通過(guò)MonetaryAmount.with()方法來(lái)調(diào)用。

格式化及解析

MonetaryAmount可以通過(guò)MonetaryAmountFormat來(lái)與字符串進(jìn)行解析/格式化。

// formatting by locale specific formatsMonetaryAmountFormat 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 stringsMonetaryAmount parsed = germanFormat.parse("12,4 USD");

可以通過(guò)AmountFormatQueryBuilder來(lái)生成自定義的格式。

// Creating a custom MonetaryAmountFormatMonetaryAmountFormat 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);

注意,這里的¤符號(hào)在模式串中是作為貨幣的占位符。

總結(jié)

新的貨幣API這里已經(jīng)介紹得差不多了。并且目前它的實(shí)現(xiàn)也已經(jīng)相對(duì)穩(wěn)定了(但還需要多補(bǔ)充些文檔)。期待能在Java 9中看到這套新的接口!

上述示例可在Github中下載到。

原文出處:Michael Scharhag

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 欧美顶级毛片在线播放小说 | 91精品久久久久久久久久 | 亚洲欧美在线观看 | 久久国产一级毛片一区二区 | 99在线视频精品 | 日本b站一卡二卡乱码入口 日本s色大片在线观看 | 久久久久久尹人网香蕉 | 国产99视频精品免费视频7 | 香港激情黄三级在线视频 | 久草在在线视频免费 | 成人日韩在线观看 | 国产在线观看成人 | 一区二区三区免费视频观看 | 深夜福利国产 | 久久精品一区二区三区四区 | 日本精品一区二区三区视频 | 高清大学生毛片一级 | 中国国产成人精品久久 | 成年人免费观看视频网站 | 日韩视频一区二区三区 | 欧美午夜精品一区二区三区 | 精品欧美一区二区三区免费观看 | 欧美日韩一级片在线观看 | 国产成人国产在线观看入口 | 国产美女啪| 亚洲国产精品热久久2022 | 全免费a级毛片免费毛视频 全午夜免费一级毛片 | 成人网久久 | 丁香五香天堂 | 99久久精品免费国产一区二区三区 | 久久视频精品36线视频在线观看 | 欧美高清videossex19 | 91国内视频 | 国产成人免费 | 一级国产在线观看高清 | 一级毛片私人影院老司机 | 国产末成年女噜噜片 | 免费看日韩欧美一级毛片 | 欧美日韩一区二区不卡三区 | 私人玩物福利视频 | 日本欧美韩国一区二区三区 |