Use concurrent instead of synchronization; Javadoc

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@1077984 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Stephen Colebourne 2011-03-04 14:59:22 +00:00
parent 1e2b9eb078
commit c21a7a26c0

View File

@ -19,12 +19,12 @@
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 @@
*/
public class LocaleUtils {
/** Unmodifiable list of available locales. */
//@GuardedBy("this")
private static List<Locale> cAvailableLocaleList; // lazily created by availableLocaleList()
/** Concurrent map of language locales by country. */
private static final ConcurrentMap<String, List<Locale>> cLanguagesByCountry =
new ConcurrentHashMap<String, List<Locale>>();
/** 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 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 static Locale toLocale(String str) {
* </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 static List<Locale> localeLookupList(Locale locale) {
*
* @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 static List<Locale> localeLookupList(Locale locale, Locale defaultLocale)
* @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 @@ private static synchronized void initAvailableLocaleList() {
* @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 static boolean isAvailableLocale(Locale locale) {
* 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 static List<Locale> languagesByCountry(String countryCode) {
* 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()));
}
}
}