Author: scolebourne
Date: Fri Mar  4 14:59:22 2011
New Revision: 1077984

URL: http://svn.apache.org/viewvc?rev=1077984&view=rev
Log:
Use concurrent instead of synchronization; Javadoc

Modified:
    
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/LocaleUtils.java

Modified: 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/LocaleUtils.java
URL: 
http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/LocaleUtils.java?rev=1077984&r1=1077983&r2=1077984&view=diff
==============================================================================
--- 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/LocaleUtils.java
 (original)
+++ 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/LocaleUtils.java
 Fri Mar  4 14:59:22 2011
@@ -19,12 +19,12 @@ package org.apache.commons.lang3;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 /**
  * <p>Operations to assist when working with a {@link Locale}.</p>
@@ -39,21 +39,13 @@ import java.util.Set;
  */
 public class LocaleUtils {
 
-    /** Unmodifiable list of available locales. */
-    //@GuardedBy("this")
-    private static List<Locale> cAvailableLocaleList; // lazily created by 
availableLocaleList()
-
-    /** Unmodifiable set of available locales. */
-    //@GuardedBy("this")
-    private static Set<Locale> cAvailableLocaleSet;   // lazily created by 
availableLocaleSet()
-
-    /** Unmodifiable map of language locales by country. */
-    private static final Map<String, List<Locale>> cLanguagesByCountry = 
-        Collections.synchronizedMap(new HashMap<String, List<Locale>>());
-
-    /** Unmodifiable map of country locales by language. */
-    private static final Map<String, List<Locale>> cCountriesByLanguage = 
-        Collections.synchronizedMap(new HashMap<String, List<Locale>>());
+    /** Concurrent map of language locales by country. */
+    private static final ConcurrentMap<String, List<Locale>> 
cLanguagesByCountry = 
+        new ConcurrentHashMap<String, List<Locale>>();
+
+    /** Concurrent map of country locales by language. */
+    private static final ConcurrentMap<String, List<Locale>> 
cCountriesByLanguage = 
+        new ConcurrentHashMap<String, List<Locale>>();
 
     /**
      * <p><code>LocaleUtils</code> instances should NOT be constructed in 
standard programming.
@@ -143,7 +135,7 @@ public class LocaleUtils {
      * </pre>
      *
      * @param locale  the locale to start from
-     * @return the unmodifiable list of Locale objects, 0 being locale, never 
null
+     * @return the unmodifiable list of Locale objects, 0 being locale, not 
null
      */
     public static List<Locale> localeLookupList(Locale locale) {
         return localeLookupList(locale, locale);
@@ -165,7 +157,7 @@ public class LocaleUtils {
      *
      * @param locale  the locale to start from, null returns empty list
      * @param defaultLocale  the default locale to use if no other is found
-     * @return the unmodifiable list of Locale objects, 0 being locale, never 
null
+     * @return the unmodifiable list of Locale objects, 0 being locale, not 
null
      */
     public static List<Locale> localeLookupList(Locale locale, Locale 
defaultLocale) {
         List<Locale> list = new ArrayList<Locale>(4);
@@ -195,22 +187,7 @@ public class LocaleUtils {
      * @return the unmodifiable list of available locales
      */
     public static List<Locale> availableLocaleList() {
-        if(cAvailableLocaleList == null) { 
-            initAvailableLocaleList(); 
-        }
-        return cAvailableLocaleList;
-    }
-
-    /**
-     * Initializes the availableLocaleList. It is separate from 
availableLocaleList() 
-     * to avoid the synchronized block affecting normal use, yet synchronized 
and 
-     * lazy loading to avoid a static block affecting other methods in this 
class. 
-     */
-    private static synchronized void initAvailableLocaleList() {
-        if(cAvailableLocaleList == null) {
-            List<Locale> list = Arrays.asList(Locale.getAvailableLocales());
-            cAvailableLocaleList = Collections.unmodifiableList(list);
-        }
+        return SyncAvoid.AVAILABLE_LOCALE_LIST;
     }
 
     //-----------------------------------------------------------------------
@@ -224,21 +201,7 @@ public class LocaleUtils {
      * @return the unmodifiable set of available locales
      */
     public static Set<Locale> availableLocaleSet() {
-        if(cAvailableLocaleSet == null) { 
-            initAvailableLocaleSet(); 
-        }
-        return cAvailableLocaleSet;
-    }
-
-    /**
-     * Initializes the availableLocaleSet. It is separate from 
availableLocaleSet() 
-     * to avoid the synchronized block affecting normal use, yet synchronized 
and 
-     * lazy loading to avoid a static block affecting other methods in this 
class. 
-     */
-    private static synchronized void initAvailableLocaleSet() {
-        if(cAvailableLocaleSet == null) {
-            cAvailableLocaleSet = Collections.unmodifiableSet( new 
HashSet<Locale>(availableLocaleList()) );
-        }
+        return SyncAvoid.AVAILABLE_LOCALE_SET;
     }
 
     //-----------------------------------------------------------------------
@@ -260,26 +223,26 @@ public class LocaleUtils {
      * languages available for that country. Variant locales are removed.</p>
      *
      * @param countryCode  the 2 letter country code, null returns empty
-     * @return an unmodifiable List of Locale objects, never null
+     * @return an unmodifiable List of Locale objects, not null
      */
     public static List<Locale> languagesByCountry(String countryCode) {
-        List<Locale> langs = cLanguagesByCountry.get(countryCode);  //syncd
+        if (countryCode == null) {
+            return Collections.emptyList();
+        }
+        List<Locale> langs = cLanguagesByCountry.get(countryCode);
         if (langs == null) {
-            if (countryCode != null) {
-                langs = new ArrayList<Locale>();
-                List<Locale> locales = availableLocaleList();
-                for (int i = 0; i < locales.size(); i++) {
-                    Locale locale = locales.get(i);
-                    if (countryCode.equals(locale.getCountry()) &&
-                            locale.getVariant().length() == 0) {
-                        langs.add(locale);
-                    }
+            langs = new ArrayList<Locale>();
+            List<Locale> locales = availableLocaleList();
+            for (int i = 0; i < locales.size(); i++) {
+                Locale locale = locales.get(i);
+                if (countryCode.equals(locale.getCountry()) &&
+                        locale.getVariant().length() == 0) {
+                    langs.add(locale);
                 }
-                langs = Collections.unmodifiableList(langs);
-            } else {
-                langs = Collections.emptyList();
             }
-            cLanguagesByCountry.put(countryCode, langs);  //syncd
+            langs = Collections.unmodifiableList(langs);
+            cLanguagesByCountry.putIfAbsent(countryCode, langs);
+            langs = cLanguagesByCountry.get(countryCode);
         }
         return langs;
     }
@@ -292,29 +255,44 @@ public class LocaleUtils {
      * countries available for that language. Variant locales are removed.</p>
      *
      * @param languageCode  the 2 letter language code, null returns empty
-     * @return an unmodifiable List of Locale objects, never null
+     * @return an unmodifiable List of Locale objects, not null
      */
     public static List<Locale> countriesByLanguage(String languageCode) {
-        List<Locale> countries = cCountriesByLanguage.get(languageCode);  
//syncd
+        if (languageCode == null) {
+            return Collections.emptyList();
+        }
+        List<Locale> countries = cCountriesByLanguage.get(languageCode);
         if (countries == null) {
-            if (languageCode != null) {
-                countries = new ArrayList<Locale>();
-                List<Locale> locales = availableLocaleList();
-                for (int i = 0; i < locales.size(); i++) {
-                    Locale locale = locales.get(i);
-                    if (languageCode.equals(locale.getLanguage()) &&
-                            locale.getCountry().length() != 0 &&
-                            locale.getVariant().length() == 0) {
-                        countries.add(locale);
-                    }
+            countries = new ArrayList<Locale>();
+            List<Locale> locales = availableLocaleList();
+            for (int i = 0; i < locales.size(); i++) {
+                Locale locale = locales.get(i);
+                if (languageCode.equals(locale.getLanguage()) &&
+                        locale.getCountry().length() != 0 &&
+                        locale.getVariant().length() == 0) {
+                    countries.add(locale);
                 }
-                countries = Collections.unmodifiableList(countries);
-            } else {
-                countries = Collections.emptyList();
             }
-            cCountriesByLanguage.put(languageCode, countries);  //syncd
+            countries = Collections.unmodifiableList(countries);
+            cCountriesByLanguage.putIfAbsent(languageCode, countries);
+            countries = cCountriesByLanguage.get(languageCode);
         }
         return countries;
     }
 
+    //-----------------------------------------------------------------------
+    // class to avoid synchronization
+    static class SyncAvoid {
+        /** Unmodifiable list of available locales. */
+        private static List<Locale> AVAILABLE_LOCALE_LIST;
+        /** Unmodifiable set of available locales. */
+        private static Set<Locale> AVAILABLE_LOCALE_SET;
+        
+        static {
+            List<Locale> list = new 
ArrayList<Locale>(Arrays.asList(Locale.getAvailableLocales()));  // extra safe
+            AVAILABLE_LOCALE_LIST = Collections.unmodifiableList(list);
+            AVAILABLE_LOCALE_SET = Collections.unmodifiableSet(new 
HashSet<Locale>(availableLocaleList()));
+        }
+    }
+
 }


Reply via email to