Java 9 の新しい通貨 API

Nov 26, 2016 am 10:10 AM
api java

JSR 354 は、Java 9 で正式に導入される予定の新しい Java 通貨 API を定義します。この記事では、JavaMoney のリファレンス実装、つまり JavaMoney の現在の進歩について見ていきます。

Java 8 の新しい日付と時刻 API に関する前回の記事と同様に、この記事では主にコードを通じて新しい API の使用法を示します。

始める前に、この仕様で定義されている新しい API セットの目的を簡単に要約したいと思います:

金銭的価値は多くのアプリケーションにとって重要な機能ですが、JDK にはありません。サポート。厳密に言えば、既存の java.util.Currency クラスは現在の ISO 4217 通貨のデータ構造を表すだけであり、関連付けられた値やカスタム通貨はありません。また、JDK には、通貨値を表す標準型はもちろん、通貨操作や変換のサポートも組み込まれていません。

Maven を使用している場合、リファレンス実装の現在の機能を体験するには、次の参照をプロジェクトに追加するだけで済みます:

<dependency>
  <groupId>org.javamoney</groupId>
  <artifactId>moneta</artifactId>
  <version>0.9</version>
</dependency>
ログイン後にコピー

仕様に記載されているクラスとインターフェイスはすべて javax.money.* パッケージの下にあります。 。

2 つのコア インターフェイス CurrencyUnit と MonetaryAmount から始めましょう。

CurrencyUnitとMonetaryAmount

CurrencyUnitは通貨を表します。これは、カスタム実装をサポートしていることを除けば、現在の java.util.Currency クラスに似ています。仕様定義から判断すると、java.util.Currency もこのインターフェースを実装できます。 CurrencyUnit のインスタンスは、MonetaryCurrency ファクトリを通じて取得できます。

// 根据货币代码来获取货币单位 CurrencyUnit euro = MonetaryCurrencies.getCurrency("EUR");
    CurrencyUnit usDollar = MonetaryCurrencies.getCurrency("USD"); // 根据国家及地区来获取货币单位
    CurrencyUnit yen = MonetaryCurrencies.getCurrency(Locale.JAPAN); CurrencyUnit
    canadianDollar = MonetaryCurrencies.getCurrency(Locale.CANADA);
ログイン後にコピー

MontetaryAmount は、特定の通貨の特定の金額を表します。通常、これは CurrencyUnit にバインドされます。

MontetaryAmountもCurrencyUnitと同様、複数の実装をサポートするインターフェースです。

CurrencyUnit と MontetaryAmount の実装は、不変で、スレッドセーフで、同等でなければなりません。

/ get MonetaryAmount from CurrencyUnit
CurrencyUnit euro = MonetaryCurrencies.getCurrency("EUR");
MonetaryAmount fiveEuro = Money.of(5, euro);
  
// get MonetaryAmount from currency code
MonetaryAmount tenUsDollar = Money.of(10, "USD");
  
// FastMoney is an alternative MonetaryAmount factory that focuses on performance
MonetaryAmount sevenEuro = FastMoney.of(7, euro);
ログイン後にコピー

Money と FastMoney は、JavaMoney ライブラリの MonetaryAmount の 2 つの実装です。 Money はデフォルトの実装で、BigDecimal を使用して金額を保存します。 FastMoney は、long 型を使用して金額を格納するオプションの実装です。ドキュメントによると、FastMoney での操作は Money での操作よりも約 10 ~ 15 倍高速です。ただし、FastMoneyの金額サイズと精度はlong型に限定されます。

ここでの Money と FastMoney はどちらも特定の実装クラスであることに注意してください (これらは javax.money.* ではなく org.javamoney.moneta.* パッケージの下にあります)。特定の型を指定したくない場合は、MonetaryAmountFactory を使用して MonetaryAmount インスタンスを生成できます:

MonetaryAmount specAmount = MonetaryAmounts.getDefaultAmountFactory()
                .setNumber(123.45) .setCurrency("USD") .create();
ログイン後にコピー

これら 2 つの MontetaryAmount インスタンスは、実装クラス、通貨単位、および値がすべて等しい場合に限り、等しいと見なされます。

MonetaryAmount oneEuro = Money.of(1, MonetaryCurrencies.getCurrency("EUR"));
boolean isEqual = oneEuro.equals(Money.of(1, "EUR")); // true
boolean isEqualFast = oneEuro.equals(FastMoney.of(1, "EUR")); // false
ログイン後にコピー

MonetaryAmount には、特定の通貨、金額、精度などを取得するために使用できる豊富なメソッドが含まれています。金額換算は非常に重要な部分です。 MonetaryAmount は、四捨五入演算子を使用して四捨五入できます:

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

ここでは、12.3456 米ドルが、現在の通貨のデフォルトの四捨五入ルールに従って変換されます。

MonetaryAmount コレクションを操作する場合、フィルター、並べ替え、グループ化に使用できる実用的なツールやメソッドが多数あります。これらのメソッドは、Java 8 のストリーム API でも使用できます。

次のコレクションを見てください:

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);
ログイン後にコピー

CurrencyUnitに基づいて金額をフィルタリングできます:

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
ログイン後にコピー

特定のしきい値より大きいまたは小さい金額をフィルタリングすることもできます:

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"));
ログイン後にコピー

並べ替えは同様です:

CurrencyUnit yen = MonetaryCurrencies.getCurrency("JPY");
CurrencyUnit dollar = MonetaryCurrencies.getCurrency("USD");
// 根据货币过滤,只返回美金
// result is [USD 18, USD 7, USD 42]
List<MonetaryAmount> onlyDollar = amounts.stream()
    .filter(MonetaryFunctions.isCurrency(dollar))
    .collect(Collectors.toList());
  
// 根据货币过滤,只返回美金和日元
// [USD 18, USD 7, JPY 13.37, USD 42]
List<MonetaryAmount> onlyDollarAndYen = amounts.stream()
    .filter(MonetaryFunctions.isCurrency(dollar, yen))
    .collect(Collectors.toList());
ログイン後にコピー

また、グループ化操作:

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());
ログイン後にコピー

MonetaryFunctions は、最大値、最小値、および合計を取得するために使用できるリダクション関数も提供します:

// 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());
ログイン後にコピー

カスタマイズされた MonetaryAmount 操作

MonetaryAmount は、MonetaryOperator と呼ばれる非常に使いやすい拡張ポイントも提供します。 MonetaryOperator は、MonetaryAmount 入力パラメータを受け取り、新しい MonetaryAmount オブジェクトを返す関数インターフェイスです。

// 按货币单位进行分组
// {USD=[USD 42, USD 7, USD 18], EUR=[EUR 2], JPY=[JPY 13.37]}
Map<CurrencyUnit, List<MonetaryAmount>> groupedByCurrency = amounts.stream()
    .collect(MonetaryFunctions.groupByCurrencyUnit());
  
// 分组并进行汇总
Map<CurrencyUnit, MonetarySummaryStatistics> 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
ログイン後にコピー

標準 API 機能はすべて、MonetaryOperator インターフェイスを通じて実装されます。たとえば、前に示した丸め操作は、MonetaryOperator インターフェイスの形式で提供されます。

為替レート

通貨の為替レートはExchangeRateProviderを通じて取得できます。 JavaMoney には、複数の異なる ExchangeRateProvider 実装が付属しています。最も重要な 2 つは、ECBCurrentRateProvider と IMFRateProvider です。

ECBCurrentRateProviderは欧州中央銀行(ECB)のデータをクエリし、IMFRateProviderは国際通貨基金(国際通貨基金、IMF)の為替レートをクエリします。

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()); //
ログイン後にコピー

ExchangeRateProvider が指定されていない場合は、CompoundRateProvider が返されます。 CompoundRateProvider は、為替レート変換リクエストを ExchangeRateProvider のチェーンに委任し、正確な結果を返す最初のプロバイダーからデータを返します。

// 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
ログイン後にコピー

通貨変換

異なる通貨間の変換は、ExchangeRateProvider によって返される CurrencyConversions を通じて完了できます。

// 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");
ログイン後にコピー

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);
ログイン後にコピー

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

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Javaの平方根 Javaの平方根 Aug 30, 2024 pm 04:26 PM

Java の平方根のガイド。ここでは、Java で平方根がどのように機能するかを、例とそのコード実装をそれぞれ示して説明します。

Javaの完全数 Javaの完全数 Aug 30, 2024 pm 04:28 PM

Java における完全数のガイド。ここでは、定義、Java で完全数を確認する方法、コード実装の例について説明します。

Java の乱数ジェネレーター Java の乱数ジェネレーター Aug 30, 2024 pm 04:27 PM

Java の乱数ジェネレーターのガイド。ここでは、Java の関数について例を挙げて説明し、2 つの異なるジェネレーターについて例を挙げて説明します。

ジャワのウェカ ジャワのウェカ Aug 30, 2024 pm 04:28 PM

Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

Javaのアームストロング数 Javaのアームストロング数 Aug 30, 2024 pm 04:26 PM

Java のアームストロング番号に関するガイド。ここでは、Java でのアームストロング数の概要とコードの一部について説明します。

Javaのスミス番号 Javaのスミス番号 Aug 30, 2024 pm 04:28 PM

Java のスミス番号のガイド。ここでは定義、Java でスミス番号を確認する方法について説明します。コード実装の例。

Java Springのインタビューの質問 Java Springのインタビューの質問 Aug 30, 2024 pm 04:29 PM

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8 Stream Foreachから休憩または戻ってきますか? Java 8 Stream Foreachから休憩または戻ってきますか? Feb 07, 2025 pm 12:09 PM

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

See all articles