This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git

commit 9d6a4be2f1ff331e51daa807fb5b81473d645f73
Author: Gary Gregory <garydgreg...@gmail.com>
AuthorDate: Thu Dec 5 16:47:25 2024 -0500

    LocaleUtils.availableLocaleSet() uses predictable iteration order
---
 src/changes/changes.xml                            |  1 +
 .../java/org/apache/commons/lang3/LocaleUtils.java | 29 +++++++++++++---------
 .../org/apache/commons/lang3/LocaleUtilsTest.java  |  3 ++-
 3 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 6de9217f3..90056faeb 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -72,6 +72,7 @@ The <action> type attribute can be add,update,fix,remove.
     <action                   type="fix" dev="ggregory" due-to="Gary 
Gregory">Make LangCollectors.collect(...) null-safe.</action>
     <action                   type="fix" dev="ggregory" due-to="IBue, Gary 
Gregory">Fix names of UTF-16 surrogate character test fixture constants, see 
also #1326.</action>
     <action                   type="fix" dev="ggregory" due-to="Gary 
Gregory">Moditect plugin generates split package warnings.</action>
+    <action                   type="fix" dev="ggregory" due-to="Gary 
Gregory">LocaleUtils.availableLocaleSet() uses predictable iteration 
order.</action>
     <!-- ADD -->
     <action                   type="add" dev="ggregory" due-to="Gary 
Gregory">Add Strings and refactor StringUtils.</action>
     <action issue="LANG-1747" type="add" dev="ggregory" due-to="Oliver B. 
Fischer, Gary Gregory">Add StopWatch.run([Failable]Runnable) and 
get([Failable]Supplier).</action>
diff --git a/src/main/java/org/apache/commons/lang3/LocaleUtils.java 
b/src/main/java/org/apache/commons/lang3/LocaleUtils.java
index d9f84712c..1e4811003 100644
--- a/src/main/java/org/apache/commons/lang3/LocaleUtils.java
+++ b/src/main/java/org/apache/commons/lang3/LocaleUtils.java
@@ -19,7 +19,8 @@ package org.apache.commons.lang3;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.HashSet;
+import java.util.Comparator;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Set;
@@ -39,17 +40,21 @@ import java.util.stream.Collectors;
  */
 public class LocaleUtils {
 
-    // class to avoid synchronization (Init on demand)
-    static class SyncAvoid {
-        /** Unmodifiable list of available locales. */
-        private static final List<Locale> AVAILABLE_LOCALE_LIST;
-        /** Unmodifiable set of available locales. */
-        private static final Set<Locale> AVAILABLE_LOCALE_SET;
+    /**
+     * Avoids synchronization, inits on demand.
+     */
+    private static final class SyncAvoid {
+
+        /** Private unmodifiable list of available locales. */
+        private static final List<Locale> AVAILABLE_LOCALE_ULIST;
+
+        /** Private unmodifiable set of available locales. */
+        private static final Set<Locale> AVAILABLE_LOCALE_USET;
 
         static {
-            final List<Locale> list = new 
ArrayList<>(Arrays.asList(Locale.getAvailableLocales()));  // extra safe
-            AVAILABLE_LOCALE_LIST = Collections.unmodifiableList(list);
-            AVAILABLE_LOCALE_SET = Collections.unmodifiableSet(new 
HashSet<>(list));
+            AVAILABLE_LOCALE_ULIST = Collections
+                    
.unmodifiableList(Arrays.asList(ArraySorter.sort(Locale.getAvailableLocales(), 
Comparator.comparing(Locale::toString))));
+            AVAILABLE_LOCALE_USET = Collections.unmodifiableSet(new 
LinkedHashSet<>(AVAILABLE_LOCALE_ULIST));
         }
     }
 
@@ -93,7 +98,7 @@ public class LocaleUtils {
      * @return the unmodifiable list of available locales
      */
     public static List<Locale> availableLocaleList() {
-        return SyncAvoid.AVAILABLE_LOCALE_LIST;
+        return SyncAvoid.AVAILABLE_LOCALE_ULIST;
     }
 
     private static List<Locale> availableLocaleList(final Predicate<Locale> 
predicate) {
@@ -110,7 +115,7 @@ public class LocaleUtils {
      * @return the unmodifiable set of available locales
      */
     public static Set<Locale> availableLocaleSet() {
-        return SyncAvoid.AVAILABLE_LOCALE_SET;
+        return SyncAvoid.AVAILABLE_LOCALE_USET;
     }
 
     /**
diff --git a/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java 
b/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java
index cf4957400..5924213c9 100644
--- a/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java
@@ -30,6 +30,7 @@ import java.lang.reflect.Constructor;
 import java.lang.reflect.Modifier;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
@@ -208,7 +209,7 @@ public class LocaleUtilsTest extends AbstractLangTest {
         assertUnmodifiableCollection(list);
 
         final Locale[] jdkLocaleArray = Locale.getAvailableLocales();
-        final List<Locale> jdkLocaleList = Arrays.asList(jdkLocaleArray);
+        final List<Locale> jdkLocaleList = 
Arrays.asList(ArraySorter.sort(jdkLocaleArray, 
Comparator.comparing(Locale::toString)));
         assertEquals(jdkLocaleList, list);
     }
 

Reply via email to