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()));
+ }
+ }
+
}