]> granicus.if.org Git - icu/commitdiff
ICU-7434 cache region-to-Currency via SoftCache
authorMarkus Scherer <markus.icu@gmail.com>
Fri, 13 May 2016 23:31:36 +0000 (23:31 +0000)
committerMarkus Scherer <markus.icu@gmail.com>
Fri, 13 May 2016 23:31:36 +0000 (23:31 +0000)
X-SVN-Rev: 38739

icu4j/main/classes/core/src/com/ibm/icu/util/Currency.java

index c8205b4d1021f7f83b6e454efec1fa23c68a691b..e3a8f0a24324ac92bd32ec914e6f8ea6d2030516 100644 (file)
@@ -26,6 +26,7 @@ import com.ibm.icu.impl.ICUData;
 import com.ibm.icu.impl.ICUDebug;
 import com.ibm.icu.impl.ICUResourceBundle;
 import com.ibm.icu.impl.SimpleCache;
+import com.ibm.icu.impl.SoftCache;
 import com.ibm.icu.impl.TextTrieMap;
 import com.ibm.icu.text.CurrencyDisplayNames;
 import com.ibm.icu.text.CurrencyMetaInfo;
@@ -228,39 +229,55 @@ public class Currency extends MeasureUnit {
     }
 
     private static final String EUR_STR = "EUR";
-    private static final ICUCache<ULocale, String> currencyCodeCache = new SimpleCache<ULocale, String>();
-    
+    private static final SoftCache<String, Currency, Void> regionCurrencyCache =
+            new SoftCache<String, Currency, Void>() {
+        @Override
+        protected Currency createInstance(String key, Void unused) {
+            return loadCurrency(key);
+        }
+    };
+
     /**
      * Instantiate a currency from resource data.
      */
     /* package */ static Currency createCurrency(ULocale loc) {
-        
         String variant = loc.getVariant();
         if ("EURO".equals(variant)) {
             return getInstance(EUR_STR);
         }
-        
-        String code = currencyCodeCache.get(loc);
-        if (code == null) {
-            String country = ULocale.getRegionForSupplementalData(loc, false);
-        
-            CurrencyMetaInfo info = CurrencyMetaInfo.getInstance();
-            List<String> list = info.currencies(CurrencyFilter.onRegion(country));
-            if (list.size() > 0) {
-                code = list.get(0);
-                boolean isPreEuro = "PREEURO".equals(variant);
-                if (isPreEuro && EUR_STR.equals(code)) {
-                    if (list.size() < 2) {
-                        return null;
-                    }
-                    code = list.get(1);
+
+        // Cache the currency by region, and whether variant=PREEURO.
+        // Minimizes the size of the cache compared with caching by ULocale.
+        String key = ULocale.getRegionForSupplementalData(loc, false);
+        if ("PREEURO".equals(variant)) {
+            key = key + '-';
+        }
+        return regionCurrencyCache.getInstance(key, null);
+    }
+
+    private static Currency loadCurrency(String key) {
+        String region;
+        boolean isPreEuro;
+        if (key.endsWith("-")) {
+            region = key.substring(0, key.length() - 1);
+            isPreEuro = true;
+        } else {
+            region = key;
+            isPreEuro = false;
+        }
+        CurrencyMetaInfo info = CurrencyMetaInfo.getInstance();
+        List<String> list = info.currencies(CurrencyFilter.onRegion(region));
+        if (!list.isEmpty()) {
+            String code = list.get(0);
+            if (isPreEuro && EUR_STR.equals(code)) {
+                if (list.size() < 2) {
+                    return null;
                 }
-            } else {
-                return null;
+                code = list.get(1);
             }
-            currencyCodeCache.put(loc, code);
+            return getInstance(code);
         }
-        return getInstance(code);
+        return null;
     }
 
     /**