001package org.apache.juneau.commons.utils;
002
003import static java.util.stream.Collectors.*;
004import static org.apache.juneau.commons.utils.AssertionUtils.*;
005import static org.apache.juneau.commons.utils.ThrowableUtils.*;
006import static org.apache.juneau.commons.utils.Utils.*;
007
008import java.lang.reflect.*;
009import java.util.*;
010import java.util.function.*;
011import java.util.stream.*;
012
013import org.apache.juneau.commons.collections.*;
014
015/*
016 * Licensed to the Apache Software Foundation (ASF) under one or more
017 * contributor license agreements.  See the NOTICE file distributed with
018 * this work for additional information regarding copyright ownership.
019 * The ASF licenses this file to You under the Apache License, Version 2.0
020 * (the "License"); you may not use this file except in compliance with
021 * the License.  You may obtain a copy of the License at
022 *
023 *      http://www.apache.org/licenses/LICENSE-2.0
024 *
025 * Unless required by applicable law or agreed to in writing, software
026 * distributed under the License is distributed on an "AS IS" BASIS,
027 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
028 * See the License for the specific language governing permissions and
029 * limitations under the License.
030 */
031
032/**
033 * Utility methods for working with collections and maps.
034 *
035 * <h5 class='section'>Complex Data Structure Construction:</h5>
036 * <p>
037 * This class provides convenient shorthand methods for creating complex nested data structures.
038 * The primary methods for building structures are:
039 * <ul>
040 *    <li>{@link #a(Object...)} - Creates arrays
041 *    <li>{@link #ao(Object...)} - Creates Object arrays (when type inference needs help)
042 *    <li>{@link #list(Object...)} / {@link #l(Object...)} - Creates modifiable lists
043 *    <li>{@link #map(Object, Object, Object, Object, Object, Object)} - Creates modifiable maps
044 *    <li>{@link #m(Object, Object, Object, Object, Object, Object)} - Creates unmodifiable maps
045 * </ul>
046 *
047 * <h5 class='section'>Examples:</h5>
048 * <p class='bjava'>
049 *    <jc>// Array of lists of maps</jc>
050 *    <jk>var</jk> <jv>data</jv> = <jsm>a</jsm>(
051 *       <jsm>l</jsm>(<jsm>m</jsm>(<js>"name"</js>, <js>"John"</js>, <js>"age"</js>, 30)),
052 *       <jsm>l</jsm>(<jsm>m</jsm>(<js>"name"</js>, <js>"Jane"</js>, <js>"age"</js>, 25))
053 *    );
054 *
055 *    <jc>// Compare with traditional Java syntax:</jc>
056 *    List&lt;Map&lt;String,Object&gt;&gt;[] <jv>data</jv> = <jk>new</jk> List[]{
057 *       <jk>new</jk> ArrayList&lt;&gt;(Arrays.asList(
058 *          <jk>new</jk> LinkedHashMap&lt;&gt;(){{
059 *             put(<js>"name"</js>, <js>"John"</js>);
060 *             put(<js>"age"</js>, 30);
061 *          }}
062 *       )),
063 *       <jk>new</jk> ArrayList&lt;&gt;(Arrays.asList(
064 *          <jk>new</jk> LinkedHashMap&lt;&gt;(){{
065 *             put(<js>"name"</js>, <js>"Jane"</js>);
066 *             put(<js>"age"</js>, 25);
067 *          }}
068 *       ))
069 *    };
070 * </p>
071 *
072 * <p class='bjava'>
073 *    <jc>// Complex nested structure: Array of lists containing maps and arrays</jc>
074 *    <jk>var</jk> <jv>complex</jv> = <jsm>a</jsm>(
075 *       <jsm>l</jsm>(
076 *          <jsm>m</jsm>(<js>"user"</js>, <js>"admin"</js>, <js>"roles"</js>, <jsm>a</jsm>(<js>"read"</js>, <js>"write"</js>, <js>"delete"</js>)),
077 *          <jsm>m</jsm>(<js>"user"</js>, <js>"guest"</js>, <js>"roles"</js>, <jsm>a</jsm>(<js>"read"</js>))
078 *       ),
079 *       <jsm>l</jsm>(
080 *          <jsm>m</jsm>(<js>"status"</js>, <js>"active"</js>, <js>"count"</js>, 42)
081 *       )
082 *    );
083 *
084 *    <jc>// Traditional Java equivalent (significantly more verbose):</jc>
085 *    List&lt;Map&lt;String,Object&gt;&gt;[] <jv>complex</jv> = <jk>new</jk> List[]{
086 *       <jk>new</jk> ArrayList&lt;&gt;(Arrays.asList(
087 *          <jk>new</jk> LinkedHashMap&lt;&gt;(){{
088 *             put(<js>"user"</js>, <js>"admin"</js>);
089 *             put(<js>"roles"</js>, <jk>new</jk> String[]{<js>"read"</js>, <js>"write"</js>, <js>"delete"</js>});
090 *          }},
091 *          <jk>new</jk> LinkedHashMap&lt;&gt;(){{
092 *             put(<js>"user"</js>, <js>"guest"</js>);
093 *             put(<js>"roles"</js>, <jk>new</jk> String[]{<js>"read"</js>});
094 *          }}
095 *       )),
096 *       <jk>new</jk> ArrayList&lt;&gt;(Arrays.asList(
097 *          <jk>new</jk> LinkedHashMap&lt;&gt;(){{
098 *             put(<js>"status"</js>, <js>"active"</js>);
099 *             put(<js>"count"</js>, 42);
100 *          }}
101 *       ))
102 *    };
103 * </p>
104 *
105 * <p class='bjava'>
106 *    <jc>// Using unmodifiable maps for immutable data</jc>
107 *    <jk>var</jk> <jv>config</jv> = <jsm>a</jsm>(
108 *       <jsm>m</jsm>(<js>"env"</js>, <js>"production"</js>, <js>"debug"</js>, <jk>false</jk>),
109 *       <jsm>m</jsm>(<js>"env"</js>, <js>"development"</js>, <js>"debug"</js>, <jk>true</jk>)
110 *    );
111 * </p>
112 *
113 * <h5 class='section'>Best Practices:</h5>
114 * <ul>
115 *    <li>Use {@link #a(Object...)} for arrays when type can be inferred, {@link #ao(Object...)} for Object arrays
116 *    <li>Use {@link #map(Object, Object, Object, Object, Object, Object)} when you need modifiable maps
117 *    <li>Use {@link #m(Object, Object, Object, Object, Object, Object)} when you need immutable/unmodifiable maps
118 *    <li>Use {@link #list(Object...)} or {@link #l(Object...)} for modifiable lists
119 *    <li>Static import these methods for maximum readability: <code>import static org.apache.juneau.commons.utils.CollectionUtils.*;</code>
120 * </ul>
121 *
122 * <h5 class='section'>See Also:</h5><ul>
123 *    <li class='link'><a class="doclink" href="../../../../../index.html#juneau-commons">juneau-commons</a>
124 * </ul>
125 */
126public class CollectionUtils {
127
128   /**
129    * Creates an array of objects.
130    *
131    * @param <T> The component type of the array.
132    * @param x The objects to place in the array.
133    * @return A new array containing the specified objects.
134    */
135   @SafeVarargs
136   public static <T> T[] a(T...x) {
137      return x;
138   }
139
140   /**
141    * Creates a 2-dimensional array.
142    *
143    * <p>
144    * This method provides a convenient way to create 2D arrays with cleaner syntax than traditional Java.
145    * While you could technically use {@code a(a(...), a(...))}, that approach fails for single-row arrays
146    * like {@code a(a(...))} because the type system collapses it into a 1D array.
147    *
148    * <h5 class='section'>Examples:</h5>
149    * <p class='bjava'>
150    *    <jc>// 2D array with multiple rows</jc>
151    *    String[][] <jv>matrix</jv> = a2(
152    *       a(<js>"a"</js>, <js>"b"</js>, <js>"c"</js>),
153    *       a(<js>"d"</js>, <js>"e"</js>, <js>"f"</js>),
154    *       a(<js>"g"</js>, <js>"h"</js>, <js>"i"</js>)
155    *    );
156    *
157    *    <jc>// Single row - this works correctly with a2()</jc>
158    *    String[][] <jv>singleRow</jv> = a2(a(<js>"x"</js>, <js>"y"</js>, <js>"z"</js>));  <jc>// Returns String[1][3]</jc>
159    *
160    *    <jc>// Without a2(), this would fail (becomes 1D array):</jc>
161    *    <jc>// String[] badAttempt = a(a("x", "y", "z"));  // Wrong! Returns String[3]</jc>
162    *
163    *    <jc>// Empty 2D array</jc>
164    *    String[][] <jv>empty</jv> = a2();  <jc>// Returns String[0][]</jc>
165    *
166    *    <jc>// Compare with traditional Java syntax:</jc>
167    *    String[][] <jv>traditional</jv> = <jk>new</jk> String[][] {
168    *       {<js>"a"</js>, <js>"b"</js>, <js>"c"</js>},
169    *       {<js>"d"</js>, <js>"e"</js>, <js>"f"</js>},
170    *       {<js>"g"</js>, <js>"h"</js>, <js>"i"</js>}
171    *    };
172    * </p>
173    *
174    * <h5 class='section'>Use Cases:</h5>
175    * <ul>
176    *    <li>Creating matrices or grids
177    *    <li>Building test data with multiple rows
178    *    <li>Representing tabular data
179    *    <li>Any scenario requiring a 2D array structure
180    * </ul>
181    *
182    * @param <E> The element type of the inner arrays.
183    * @param value The 1D arrays that will become rows in the 2D array.
184    * @return A 2D array containing the specified rows.
185    */
186   @SafeVarargs
187   public static <E> E[][] a2(E[]...value) {
188      return value;
189   }
190
191   /**
192    * Traverses all elements in the specified object and accumulates them into a list.
193    *
194    * @param <T> The element type.
195    * @param o The object to traverse.
196    * @return A list containing all accumulated elements.
197    */
198   @SuppressWarnings("unchecked")
199   public static <T> List<T> accumulate(Object o) {
200      var l = list();
201      traverse(o, l::add);
202      return (List<T>)l;
203   }
204
205   /**
206    * Adds all the specified values to the specified collection.
207    * Creates a new set if the value is <jk>null</jk>.
208    *
209    * @param <E> The element type.
210    * @param value The collection to add to.
211    * @param entries The entries to add.
212    * @return The set.
213    */
214   @SafeVarargs
215   public static <E> List<E> addAll(List<E> value, E...entries) {
216      if (nn(entries)) {
217         if (value == null)
218            value = list(entries);
219         else
220            Collections.addAll(value, entries);
221      }
222      return value;
223   }
224
225   /**
226    * Adds all the specified values to the specified collection.
227    * Creates a new set if the value is <jk>null</jk>.
228    *
229    * @param <E> The element type.
230    * @param value The collection to add to.
231    * @param entries The entries to add.
232    * @return The set.
233    */
234   public static <E> List<E> addAll(List<E> value, List<E> entries) {
235      if (nn(entries)) {
236         if (value == null)
237            value = copyOf(entries);
238         else
239            value.addAll(entries);
240      }
241      return value;
242   }
243
244   /**
245    * Adds all the specified values to the specified collection.
246    * Creates a new set if the value is <jk>null</jk>.
247    *
248    * @param <E> The element type.
249    * @param value The collection to add to.
250    * @param entries The entries to add.
251    * @return The set.
252    */
253   @SafeVarargs
254   public static <E> Set<E> addAll(Set<E> value, E...entries) {
255      if (nn(entries)) {
256         if (value == null)
257            value = set(entries);
258         else
259            Collections.addAll(value, entries);
260      }
261      return value;
262   }
263
264   /**
265    * Adds all the specified values to the specified collection.
266    * Creates a new set if the value is <jk>null</jk>.
267    *
268    * @param <E> The element type.
269    * @param value The collection to add to.
270    * @param entries The entries to add.
271    * @return The set.
272    */
273   @SafeVarargs
274   public static <E> SortedSet<E> addAll(SortedSet<E> value, E...entries) {
275      if (nn(entries)) {
276         if (value == null)
277            value = sortedSet(entries);
278         else
279            Collections.addAll(value, entries);
280      }
281      return value;
282   }
283
284   /**
285    * Appends one or more elements to an array.
286    *
287    * @param <T> The element type.
288    * @param array The array to append to.
289    * @param newElements The new elements to append to the array.
290    * @return A new array with the specified elements appended.
291    */
292   @SuppressWarnings("unchecked")
293   public static <T> T[] addAll(T[] array, T...newElements) {
294      if (array == null)
295         return newElements;
296      if (newElements.length == 0)
297         return array;
298      var a = (T[])Array.newInstance(array.getClass().getComponentType(), array.length + newElements.length);
299      for (var i = 0; i < array.length; i++)
300         a[i] = array[i];
301      for (var i = 0; i < newElements.length; i++)
302         a[i + array.length] = newElements[i];
303      return a;
304   }
305
306   /**
307    * Creates an array of objects with the return type explicitly set to {@code Object[]}.
308    *
309    * <p>
310    * This method is useful when you need to force the return type to be {@code Object[]} regardless of
311    * the actual types of the elements passed in. This is particularly helpful in scenarios where:
312    * <ul>
313    *    <li>You're mixing different types in the same array
314    *    <li>You need to avoid type inference issues with the generic {@link #a(Object...) a()} method
315    *    <li>You're working with APIs that specifically require {@code Object[]}
316    *    <li>You want to ensure maximum flexibility in what can be stored in the array
317    * </ul>
318    *
319    * <h5 class='section'>Examples:</h5>
320    * <p class='bjava'>
321    *    <jc>// Mixed types - works perfectly with ao()</jc>
322    *    Object[] <jv>mixed</jv> = ao(<js>"string"</js>, 42, <jk>true</jk>, 3.14, <jk>null</jk>);
323    *
324    *    <jc>// Force Object[] return type even for uniform types</jc>
325    *    Object[] <jv>strings</jv> = ao(<js>"a"</js>, <js>"b"</js>, <js>"c"</js>);  <jc>// Returns Object[], not String[]</jc>
326    *
327    *    <jc>// Compare with a() which infers the most specific type:</jc>
328    *    String[] <jv>typed</jv> = a(<js>"a"</js>, <js>"b"</js>, <js>"c"</js>);     <jc>// Returns String[]</jc>
329    *
330    *    <jc>// Useful when you need Object[] for APIs:</jc>
331    *    <jk>void</jk> someMethod(Object[] args) { ... }
332    *    someMethod(ao(<js>"test"</js>, 123, <jk>true</jk>));  <jc>// No type issues</jc>
333    *
334    *    <jc>// Empty Object array</jc>
335    *    Object[] <jv>empty</jv> = ao();
336    *
337    *    <jc>// With null values</jc>
338    *    Object[] <jv>withNulls</jv> = ao(<js>"value"</js>, <jk>null</jk>, 42, <jk>null</jk>);
339    * </p>
340    *
341    * <h5 class='section'>When to Use:</h5>
342    * <ul>
343    *    <li>Use {@link #a(Object...) a()} when you want type inference for homogeneous arrays
344    *    <li>Use {@code ao()} when you explicitly need {@code Object[]} or have mixed types
345    * </ul>
346    *
347    * @param value The objects to place in the array.
348    * @return A new {@code Object[]} containing the specified objects.
349    */
350   public static Object[] ao(Object...value) {
351      return value;
352   }
353
354   /**
355    * Creates an array of the specified component type and length.
356    *
357    * @param <E> The component type of the array.
358    * @param componentType The component type of the array.
359    * @param length The length of the array.
360    * @return A new array of the specified type and length. Never <jk>null</jk>.
361    */
362   @SuppressWarnings("unchecked")
363   public static <E> E[] array(Class<E> componentType, int length) {
364      return (E[])Array.newInstance(componentType, length);
365   }
366
367   /**
368    * Converts the specified collection to an array.
369    *
370    * @param <E> The element type.
371    * @param value The collection to convert.
372    * @param componentType The component type of the array.
373    * @return A new array.
374    */
375   @SuppressWarnings("unchecked")
376   public static <E> E[] array(Collection<E> value, Class<E> componentType) {
377      assertArgNotNull("value", value);
378      var array = (E[])Array.newInstance(componentType, value.size());
379      return value.toArray(array);
380   }
381
382   /**
383    * Converts any array (including primitive arrays) to a List.
384    *
385    * @param array The array to convert. Can be any array type including primitives.
386    * @return A List containing the array elements. Primitive values are auto-boxed.
387    *         Returns null if the input is null.
388    * @throws IllegalArgumentException if the input is not an array.
389    */
390   public static List<Object> arrayToList(Object array) {
391      assertArgNotNull("array", array);
392      assertArg(isArray(array), "Input must be an array but was {0}", cn(array));
393
394      var componentType = array.getClass().getComponentType();
395      var length = Array.getLength(array);
396      var result = new ArrayList<>(length);
397
398      // Handle primitive arrays specifically for better performance
399      if (componentType.isPrimitive()) {
400         if (componentType == int.class) {
401            var arr = (int[])array;
402            for (var value : arr) {
403               result.add(value);
404            }
405         } else if (componentType == long.class) {
406            var arr = (long[])array;
407            for (var value : arr) {
408               result.add(value);
409            }
410         } else if (componentType == double.class) {
411            var arr = (double[])array;
412            for (var value : arr) {
413               result.add(value);
414            }
415         } else if (componentType == float.class) {
416            var arr = (float[])array;
417            for (var value : arr) {
418               result.add(value);
419            }
420         } else if (componentType == boolean.class) {
421            var arr = (boolean[])array;
422            for (var value : arr) {
423               result.add(value);
424            }
425         } else if (componentType == byte.class) {
426            var arr = (byte[])array;
427            for (var value : arr) {
428               result.add(value);
429            }
430         } else if (componentType == char.class) {
431            var arr = (char[])array;
432            for (var value : arr) {
433               result.add(value);
434            }
435         } else /* (componentType == short.class) */ {
436            var arr = (short[])array;
437            for (var value : arr) {
438               result.add(value);
439            }
440         }
441      } else {
442         // Handle Object arrays
443         for (var i = 0; i < length; i++) {
444            result.add(Array.get(array, i));
445         }
446      }
447
448      return result;
449   }
450
451   /**
452    * Shortcut for creating a boolean array.
453    *
454    * <h5 class='section'>Example:</h5>
455    * <p class='bjava'>
456    *    <jk>boolean</jk>[] <jv>myArray</jv> = <jsm>booleans</jsm>(<jk>true</jk>, <jk>false</jk>, <jk>true</jk>);
457    * </p>
458    *
459    * @param value The values to initialize the array with.
460    * @return A new boolean array.
461    */
462   public static boolean[] booleans(boolean...value) {
463      return value;
464   }
465
466   /**
467    * Shortcut for creating a byte array.
468    *
469    * <p>Accepts int values and converts them to bytes, eliminating the need for explicit byte casts.</p>
470    *
471    * <h5 class='section'>Example:</h5>
472    * <p class='bjava'>
473    *    <jk>byte</jk>[] <jv>myArray</jv> = <jsm>bytes</jsm>(1, 2, 3);
474    * </p>
475    *
476    * @param value The int values to convert to bytes. Values outside the byte range (-128 to 127) will be truncated.
477    * @return A new byte array.
478    */
479   public static byte[] bytes(int...value) {
480      var result = new byte[value.length];
481      for (var i = 0; i < value.length; i++) {
482         result[i] = (byte)value[i];
483      }
484      return result;
485   }
486
487   /**
488    * Shortcut for creating a char array.
489    *
490    * <h5 class='section'>Example:</h5>
491    * <p class='bjava'>
492    *    <jk>char</jk>[] <jv>myArray</jv> = <jsm>chars</jsm>(<js>'a'</js>, <js>'b'</js>, <js>'c'</js>);
493    * </p>
494    *
495    * @param value The values to initialize the array with.
496    * @return A new char array.
497    */
498   public static char[] chars(char...value) {
499      return value;
500   }
501
502   /**
503    * Combine an arbitrary number of arrays into a single array.
504    *
505    * @param <E> The element type.
506    * @param arrays Collection of arrays to combine.
507    * @return A new combined array, or <jk>null</jk> if all arrays are <jk>null</jk>.
508    */
509   @SuppressWarnings("unchecked")
510   public static <E> E[] combine(E[]...arrays) {
511      assertArgNotNull("arrays", arrays);
512      int l = 0;
513      E[] a1 = null;
514      for (var a : arrays) {
515         if (a1 == null && nn(a))
516            a1 = a;
517         l += (a == null ? 0 : a.length);
518      }
519      if (a1 == null)
520         return null;
521      var a = (E[])Array.newInstance(a1.getClass().getComponentType(), l);
522      int i = 0;
523      for (var aa : arrays)
524         if (nn(aa))
525            for (var t : aa)
526               a[i++] = t;
527      return a;
528   }
529
530   /**
531    * Returns <jk>true</jk> if the specified array contains the specified element using the {@link String#equals(Object)}
532    * method.
533    *
534    * @param element The element to check for.
535    * @param array The array to check.
536    * @return
537    *    <jk>true</jk> if the specified array contains the specified element,
538    *    <jk>false</jk> if the array or element is <jk>null</jk>.
539    */
540   public static <T> boolean contains(T element, T[] array) {
541      return indexOf(element, array) != -1;
542   }
543
544   /**
545    * Copies the specified array into the specified list.
546    *
547    * <p>
548    * Works on both object and primitive arrays.
549    *
550    * @param array The array to copy into a list.
551    * @param list The list to copy the values into.
552    * @return The same list passed in.
553    */
554   @SuppressWarnings({ "unchecked", "rawtypes" })
555   public static List copyArrayToList(Object array, List list) {
556      if (nn(array)) {
557         var length = Array.getLength(array);
558         for (var i = 0; i < length; i++)
559            list.add(Array.get(array, i));
560      }
561      return list;
562   }
563
564   /**
565    * Creates a new collection from the specified collection.
566    *
567    * @param <E> The element type.
568    * @param val The value to copy from.
569    * @return A new {@link LinkedHashSet}, or <jk>null</jk> if the input was null.
570    */
571   public static <E> Collection<E> copyOf(Collection<E> val) {
572      return val == null ? null : new LinkedHashSet<>(val);
573   }
574
575   /**
576    * Convenience method for copying a list.
577    *
578    * @param <E> The element type.
579    * @param value The list to copy.
580    * @return A new modifiable list.
581    */
582   public static <E> ArrayList<E> copyOf(List<E> value) {
583      return value == null ? null : new ArrayList<>(value);
584   }
585
586   /**
587    * Makes a deep copy of the specified list.
588    *
589    * @param l The list to copy.
590    * @param valueMapper The function to apply to each value in the list.
591    * @param <E> The entry type.
592    * @return A new list with the same values as the specified list, but with values transformed by the specified function.  Null if the list being copied was null.
593    */
594   public static <E> List<E> copyOf(List<E> l, Function<? super E,? extends E> valueMapper) {
595      return copyOf(l, valueMapper, LinkedList::new);
596   }
597
598   /**
599    * Makes a deep copy of the specified list.
600    *
601    * @param l The list to copy.
602    * @param valueMapper The function to apply to each value in the list.
603    * @param <E> The entry type.
604    * @param listFactory The factory for creating the list.
605    * @return A new list with the same values as the specified list, but with values transformed by the specified function.  Null if the list being copied was null.
606    */
607   public static <E> List<E> copyOf(List<E> l, Function<? super E,? extends E> valueMapper, Supplier<List<E>> listFactory) {
608      return l == null ? null : l.stream().map(valueMapper).collect(toCollection(listFactory));
609   }
610
611   /**
612    * Creates a new map from the specified map.
613    *
614    * @param <K> The key type.
615    * @param <V> The value type.
616    * @param val The value to copy from.
617    * @return A new {@link LinkedHashMap}, or <jk>null</jk> if the input was null.
618    */
619   public static <K,V> Map<K,V> copyOf(Map<K,V> val) {
620      return val == null ? null : new LinkedHashMap<>(val);
621   }
622
623   /**
624    * Makes a deep copy of the specified map.
625    *
626    * @param <K> The key type.
627    * @param <V> The value type.
628    * @param m The map to copy.
629    * @param valueMapper The function to apply to each value in the map.
630    * @return A new map with the same keys as the specified map, but with values transformed by the specified function.  Null if the map being copied was null.
631    */
632   public static <K,V> Map<K,V> copyOf(Map<K,V> m, Function<? super V,? extends V> valueMapper) {
633      return copyOf(m, valueMapper, LinkedHashMap::new);
634   }
635
636   /**
637    * Makes a deep copy of the specified map.
638    *
639    * @param <K> The key type.
640    * @param <V> The value type.
641    * @param m The map to copy.
642    * @param valueMapper The function to apply to each value in the map.
643    * @param mapFactory The factory for creating the map.
644    * @return A new map with the same keys as the specified map, but with values transformed by the specified function.  Null if the map being copied was null.
645    */
646   public static <K,V> Map<K,V> copyOf(Map<K,V> m, Function<? super V,? extends V> valueMapper, Supplier<Map<K,V>> mapFactory) {
647      return m == null ? null : m.entrySet().stream().collect(toMap(Map.Entry::getKey, e -> valueMapper.apply(e.getValue()), (a, b) -> b, mapFactory));
648   }
649
650   /**
651    * Creates a new set from the specified collection.
652    *
653    * @param <E> The element type.
654    * @param val The value to copy from.
655    * @return A new {@link LinkedHashSet}, or <jk>null</jk> if the input was null.
656    */
657   public static <E> Set<E> copyOf(Set<E> val) {
658      return val == null ? null : new LinkedHashSet<>(val);
659   }
660
661   /**
662    * Makes a deep copy of the specified list.
663    *
664    * @param l The list to copy.
665    * @param valueMapper The function to apply to each value in the list.
666    * @param <E> The entry type.
667    * @return A new list with the same values as the specified list, but with values transformed by the specified function.  Null if the list being copied was null.
668    */
669   public static <E> Set<E> copyOf(Set<E> l, Function<? super E,? extends E> valueMapper) {
670      return copyOf(l, valueMapper, LinkedHashSet::new);
671   }
672
673   /**
674    * Makes a deep copy of the specified list.
675    *
676    * @param l The list to copy.
677    * @param valueMapper The function to apply to each value in the list.
678    * @param <E> The entry type.
679    * @param setFactory The factory for creating sets.
680    * @return A new list with the same values as the specified list, but with values transformed by the specified function.  Null if the list being copied was null.
681    */
682   public static <E> Set<E> copyOf(Set<E> l, Function<? super E,? extends E> valueMapper, Supplier<Set<E>> setFactory) {
683      return l == null ? null : l.stream().map(valueMapper).collect(toCollection(setFactory));
684   }
685
686   /**
687    * Makes a copy of the specified array.
688    *
689    * @param array The array to copy.
690    * @param <T> The element type.
691    * @return A new copy of the array, or <jk>null</jk> if the array was <jk>null</jk>.s
692    */
693   public static <T> T[] copyOf(T[] array) {
694      return array == null ? null : Arrays.copyOf(array, array.length);
695   }
696
697   /**
698    * Shortcut for creating a double array.
699    *
700    * <h5 class='section'>Example:</h5>
701    * <p class='bjava'>
702    *    <jk>double</jk>[] <jv>myArray</jv> = <jsm>doubles</jsm>(1.0, 2.0, 3.0);
703    * </p>
704    *
705    * @param value The values to initialize the array with.
706    * @return A new double array.
707    */
708   public static double[] doubles(double...value) {
709      return value;
710   }
711
712   /**
713    * Returns the first element in a list.
714    *
715    * @param <E> The element type.
716    * @param l The list. Can be <jk>null</jk>.
717    * @return The first element in the list, or <jk>null</jk> if the list is <jk>null</jk> or empty.
718    */
719   public static <E> E first(List<E> l) {
720      return e(l) ? null : l.get(0);
721   }
722
723   /**
724    * Shortcut for creating a float array.
725    *
726    * <h5 class='section'>Example:</h5>
727    * <p class='bjava'>
728    *    <jk>float</jk>[] <jv>myArray</jv> = <jsm>floats</jsm>(1.0f, 2.0f, 3.0f);
729    * </p>
730    *
731    * @param value The values to initialize the array with.
732    * @return A new float array.
733    */
734   public static float[] floats(float...value) {
735      return value;
736   }
737
738   /**
739    * Iterates the specified array in reverse order.
740    *
741    * @param <E> The element type.
742    * @param value The array to iterate.
743    * @param action The action to perform.
744    */
745   public static <E> void forEachReverse(E[] value, Consumer<E> action) {
746      for (var i = value.length - 1; i >= 0; i--)
747         action.accept(value[i]);
748   }
749
750   /**
751    * Iterates the specified list in reverse order.
752    *
753    * @param <E> The element type.
754    * @param value The list to iterate.
755    * @param action The action to perform.
756    */
757   public static <E> void forEachReverse(List<E> value, Consumer<E> action) {
758      if (value instanceof ArrayList) {
759         for (var i = value.size() - 1; i >= 0; i--)
760            action.accept(value.get(i));
761      } else {
762         ListIterator<E> i = value.listIterator(value.size());
763         while (i.hasPrevious())
764            action.accept(i.previous());
765      }
766   }
767
768   /**
769    * Returns the index position of the element in the specified array using the {@link String#equals(Object)} method.
770    *
771    * @param element The element to check for.
772    * @param array The array to check.
773    * @return
774    *    The index position of the element in the specified array, or
775    *    <c>-1</c> if the array doesn't contain the element, or the array or element is <jk>null</jk>.
776    */
777   public static <T> int indexOf(T element, T[] array) {
778      if (element == null || array == null)
779         return -1;
780      for (var i = 0; i < array.length; i++)
781         if (eq(element, array[i]))
782            return i;
783      return -1;
784   }
785
786   /**
787    * Shortcut for creating an int array.
788    *
789    * <h5 class='section'>Example:</h5>
790    * <p class='bjava'>
791    *    <jk>int</jk>[] <jv>myArray</jv> = <jsm>ints</jsm>(1, 2, 3);
792    * </p>
793    *
794    * @param value The values to initialize the array with.
795    * @return A new int array.
796    */
797   public static int[] ints(int...value) {
798      return value;
799   }
800
801   /**
802    * Returns <jk>true</jk> if the specified array is null or has a length of zero.
803    *
804    * @param array The array to check.
805    * @return <jk>true</jk> if the specified array is null or has a length of zero.
806    */
807   public static boolean isEmptyArray(Object[] array) {
808      return array == null || array.length == 0;
809   }
810
811   /**
812    * Returns <jk>true</jk> if the specified array is not null and has a length greater than zero.
813    *
814    * @param array The array to check.
815    * @return <jk>true</jk> if the specified array is not null and has a length greater than zero.
816    */
817   public static boolean isNotEmptyArray(Object[] array) {
818      return nn(array) && array.length > 0;
819   }
820
821   /**
822    * Shortcut for creating an unmodifiable list out of an array of values.
823    *
824    * @param <T> The element type.
825    * @param values The values to add to the list.
826    * @return An unmodifiable list containing the specified values, or <jk>null</jk> if the input is <jk>null</jk>.
827    */
828   @SafeVarargs
829   public static <T> List<T> l(T...values) {  // NOSONAR
830      return values == null ? null : Arrays.asList(values);
831   }
832
833   /**
834    * Returns the last entry in an array.
835    *
836    * @param <E> The element type.
837    * @param l The array.
838    * @return The last element, or <jk>null</jk> if the array is <jk>null</jk> or empty.
839    */
840   public static <E> E last(E[] l) {
841      return (l == null || l.length == 0) ? null : l[l.length - 1];
842   }
843
844   /**
845    * Returns the last entry in a list.
846    *
847    * @param <E> The element type.
848    * @param l The list.
849    * @return The last element, or <jk>null</jk> if the list is <jk>null</jk> or empty.
850    */
851   public static <E> E last(List<E> l) {
852      return e(l) ? null : l.get(l.size() - 1);
853   }
854
855   /**
856    * Returns the length of the specified array.
857    *
858    * <p>
859    * This is a null-safe convenience method that wraps {@link Array#getLength(Object)}.
860    * Works with both object arrays and primitive arrays.
861    *
862    * <h5 class='section'>Example:</h5>
863    * <p class='bjava'>
864    *    String[] <jv>array1</jv> = {<js>"foo"</js>, <js>"bar"</js>};
865    *    <jk>int</jk>[] <jv>array2</jv> = {1, 2, 3};
866    *
867    *    <jk>int</jk> <jv>len1</jv> = length(<jv>array1</jv>);  <jc>// Returns 2</jc>
868    *    <jk>int</jk> <jv>len2</jv> = length(<jv>array2</jv>);  <jc>// Returns 3</jc>
869    *    <jk>int</jk> <jv>len3</jv> = length(<jk>null</jk>);    <jc>// Returns 0</jc>
870    * </p>
871    *
872    * @param array The array object. Can be <jk>null</jk>.
873    * @return The length of the array, or <c>0</c> if the array is <jk>null</jk> or not an array.
874    */
875   public static int length(Object array) {
876      if (array == null)
877         return 0;
878      assertArg(array.getClass().isArray(), "Object is not an array");
879      return Array.getLength(array);
880   }
881
882   /**
883    * Shortcut for creating a modifiable list out of an array of values.
884    *
885    * @param <T> The element type.
886    * @param values The values to add to the list.
887    * @return A modifiable list containing the specified values.
888    */
889   @SafeVarargs
890   public static <T> List<T> list(T...values) {  // NOSONAR
891      return new ArrayList<>(l(values));
892   }
893
894   /**
895    * Shortcut for creating an ArrayList from the specified values.
896    *
897    * <p>
898    * This is a convenience method that creates a modifiable ArrayList.
899    *
900    * <h5 class='section'>Example:</h5>
901    * <p class='bjava'>
902    *    List&lt;String&gt; <jv>list</jv> = al(<js>"a"</js>, <js>"b"</js>, <js>"c"</js>);
903    * </p>
904    *
905    * @param <T> The element type.
906    * @param values The values to add to the list.
907    * @return A new modifiable ArrayList containing the specified values.
908    * @see #list(Object...)
909    */
910   @SafeVarargs
911   public static <T> ArrayList<T> al(T...values) {  // NOSONAR
912      return new ArrayList<>(l(values));
913   }
914
915   /**
916    * Shortcut for creating a LinkedList from the specified values.
917    *
918    * <p>
919    * This is a convenience method that creates a modifiable LinkedList.
920    *
921    * <h5 class='section'>Example:</h5>
922    * <p class='bjava'>
923    *    List&lt;String&gt; <jv>list</jv> = ll(<js>"a"</js>, <js>"b"</js>, <js>"c"</js>);
924    * </p>
925    *
926    * @param <T> The element type.
927    * @param values The values to add to the list.
928    * @return A new modifiable LinkedList containing the specified values.
929    */
930   @SafeVarargs
931   public static <T> LinkedList<T> ll(T...values) {  // NOSONAR
932      return new LinkedList<>(l(values));
933   }
934
935   /**
936    * Shortcut for creating a HashSet from the specified values.
937    *
938    * <p>
939    * This is a convenience method that creates a modifiable HashSet.
940    *
941    * <h5 class='section'>Example:</h5>
942    * <p class='bjava'>
943    *    Set&lt;String&gt; <jv>set</jv> = hs(<js>"a"</js>, <js>"b"</js>, <js>"c"</js>);
944    * </p>
945    *
946    * @param <T> The element type.
947    * @param values The values to add to the set.
948    * @return A new modifiable HashSet containing the specified values.
949    */
950   @SafeVarargs
951   public static <T> HashSet<T> hs(T...values) {  // NOSONAR
952      return new HashSet<>(Arrays.asList(values));
953   }
954
955   /**
956    * Shortcut for creating a TreeSet from the specified values.
957    *
958    * <p>
959    * This is a convenience method that creates a modifiable TreeSet.
960    * Values must be comparable.
961    *
962    * <h5 class='section'>Example:</h5>
963    * <p class='bjava'>
964    *    Set&lt;String&gt; <jv>set</jv> = ts(<js>"c"</js>, <js>"a"</js>, <js>"b"</js>);  <jc>// Sorted: a, b, c</jc>
965    * </p>
966    *
967    * @param <T> The element type (must be Comparable).
968    * @param values The values to add to the set.
969    * @return A new modifiable TreeSet containing the specified values.
970    */
971   @SafeVarargs
972   public static <T extends Comparable<T>> TreeSet<T> ts(T...values) {  // NOSONAR
973      return new TreeSet<>(Arrays.asList(values));
974   }
975
976   /**
977    * Convenience factory for a {@link Lists}.
978    *
979    * @param <E> The element type.
980    * @param type The element type.
981    * @return A new list builder.
982    */
983   public static <E> Lists<E> listb(Class<E> type) {
984      return Lists.create(type);
985   }
986
987   /**
988    * Shortcut for creating an empty list.
989    *
990    * <p>
991    * This is a convenience method that provides a more concise syntax than {@link Collections#emptyList()}.
992    * The "e" suffix indicates "empty".
993    *
994    * <h5 class='section'>Example:</h5>
995    * <p class='bjava'>
996    *    List&lt;String&gt; <jv>myList</jv> = <jsm>liste</jsm>();
997    * </p>
998    *
999    * @param <T> The element type.
1000    * @return An empty unmodifiable list.
1001    */
1002   public static <T> List<T> liste() {
1003      return Collections.emptyList();
1004   }
1005
1006   /**
1007    * Shortcut for creating an empty list of the specified type.
1008    *
1009    * @param <T> The element type.
1010    * @param type The element type class.
1011    * @return An empty list.
1012    */
1013   public static <T> List<T> liste(Class<T> type) {
1014      return Collections.emptyList();
1015   }
1016
1017   /**
1018    * Returns a null list.
1019    *
1020    * @param <T> The element type.
1021    * @param type The element type class.
1022    * @return <jk>null</jk>.
1023    */
1024   public static <T> List<T> listn(Class<T> type) {
1025      return null;
1026   }
1027
1028   /**
1029    * Convenience method for creating an {@link ArrayList}.
1030    *
1031    * @param <E> The element type.
1032    * @param elementType The element type.
1033    * @param values The values to initialize the list with.
1034    * @return A new modifiable list.
1035    */
1036   @SafeVarargs
1037   public static <E> List<E> listOf(Class<E> elementType, E...values) {
1038      return list(values);
1039   }
1040
1041   /**
1042    * Convenience method for creating an {@link ArrayList} of the specified size.
1043    *
1044    * @param <E> The element type.
1045    * @param size The initial size of the list.
1046    * @return A new modifiable list.
1047    */
1048   public static <E> ArrayList<E> listOfSize(int size) {
1049      return new ArrayList<>(size);
1050   }
1051
1052   /**
1053    * Shortcut for creating a long array.
1054    *
1055    * <h5 class='section'>Example:</h5>
1056    * <p class='bjava'>
1057    *    <jk>long</jk>[] <jv>myArray</jv> = <jsm>longs</jsm>(1L, 2L, 3L);
1058    * </p>
1059    *
1060    * @param value The values to initialize the array with.
1061    * @return A new long array.
1062    */
1063   public static long[] longs(long...value) {
1064      return value;
1065   }
1066
1067   /**
1068    * Convenience method for creating an unmodifiable map.
1069    *
1070    * @param <K> The key type.
1071    * @param <V> The value type.
1072    * @return A new unmodifiable empty map.
1073    */
1074   public static <K,V> Map<K,V> m() {
1075      return Map.of();
1076   }
1077
1078   /**
1079    * Convenience method for creating an unmodifiable map.
1080    * Unlike Map.of(...), supports null keys/values and preserves insertion order.
1081    *
1082    * @param <K> The key type.
1083    * @param <V> The value type.
1084    * @param k1 Key 1.
1085    * @param v1 Value 1.
1086    * @return A new unmodifiable map.
1087    */
1088   public static <K,V> Map<K,V> m(K k1, V v1) {
1089      return new SimpleMap<>(a(k1), a(v1));
1090   }
1091
1092   /**
1093    * Convenience method for creating an unmodifiable map.
1094    * Unlike Map.of(...), supports null keys/values and preserves insertion order.
1095    *
1096    * @param <K> The key type.
1097    * @param <V> The value type.
1098    * @param k1 Key 1.
1099    * @param v1 Value 1.
1100    * @param k2 Key 2.
1101    * @param v2 Value 2.
1102    * @return A new unmodifiable map.
1103    */
1104   public static <K,V> Map<K,V> m(K k1, V v1, K k2, V v2) {
1105      return new SimpleMap<>(a(k1, k2), a(v1, v2));
1106   }
1107
1108   /**
1109    * Convenience method for creating an unmodifiable map.
1110    * Unlike Map.of(...), supports null keys/values and preserves insertion order.
1111    *
1112    * @param <K> The key type.
1113    * @param <V> The value type.
1114    * @param k1 Key 1.
1115    * @param v1 Value 1.
1116    * @param k2 Key 2.
1117    * @param v2 Value 2.
1118    * @param k3 Key 3.
1119    * @param v3 Value 3.
1120    * @return A new unmodifiable map.
1121    */
1122   public static <K,V> Map<K,V> m(K k1, V v1, K k2, V v2, K k3, V v3) {
1123      return new SimpleMap<>(a(k1, k2, k3), a(v1, v2, v3));
1124   }
1125
1126   /**
1127    * Convenience method for creating an unmodifiable map.
1128    * Unlike Map.of(...), supports null keys/values and preserves insertion order.
1129    *
1130    * @param <K> The key type.
1131    * @param <V> The value type.
1132    * @param k1 Key 1.
1133    * @param v1 Value 1.
1134    * @param k2 Key 2.
1135    * @param v2 Value 2.
1136    * @param k3 Key 3.
1137    * @param v3 Value 3.
1138    * @param k4 Key 4.
1139    * @param v4 Value 4.
1140    * @return A new unmodifiable map.
1141    */
1142   public static <K,V> Map<K,V> m(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
1143      return new SimpleMap<>(a(k1, k2, k3, k4), a(v1, v2, v3, v4));
1144   }
1145
1146   /**
1147    * Convenience method for creating an unmodifiable map.
1148    * Unlike Map.of(...), supports null keys/values and preserves insertion order.
1149    *
1150    * @param <K> The key type.
1151    * @param <V> The value type.
1152    * @param k1 Key 1.
1153    * @param v1 Value 1.
1154    * @param k2 Key 2.
1155    * @param v2 Value 2.
1156    * @param k3 Key 3.
1157    * @param v3 Value 3.
1158    * @param k4 Key 4.
1159    * @param v4 Value 4.
1160    * @param k5 Key 5.
1161    * @param v5 Value 5.
1162    * @return A new unmodifiable map.
1163    */
1164   public static <K,V> Map<K,V> m(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
1165      return new SimpleMap<>(a(k1, k2, k3, k4, k5), a(v1, v2, v3, v4, v5));
1166   }
1167
1168   /**
1169    * Convenience method for creating an unmodifiable map.
1170    * Unlike Map.of(...), supports null keys/values and preserves insertion order.
1171    *
1172    * @param <K> The key type.
1173    * @param <V> The value type.
1174    * @param k1 Key 1.
1175    * @param v1 Value 1.
1176    * @param k2 Key 2.
1177    * @param v2 Value 2.
1178    * @param k3 Key 3.
1179    * @param v3 Value 3.
1180    * @param k4 Key 4.
1181    * @param v4 Value 4.
1182    * @param k5 Key 5.
1183    * @param v5 Value 5.
1184    * @param k6 Key 6.
1185    * @param v6 Value 6.
1186    * @return A new unmodifiable map.
1187    */
1188   public static <K,V> Map<K,V> m(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) {
1189      return new SimpleMap<>(a(k1, k2, k3, k4, k5, k6), a(v1, v2, v3, v4, v5, v6));
1190   }
1191
1192   /**
1193    * Convenience method for creating an unmodifiable map.
1194    * Unlike Map.of(...), supports null keys/values and preserves insertion order.
1195    *
1196    * @param <K> The key type.
1197    * @param <V> The value type.
1198    * @param k1 Key 1.
1199    * @param v1 Value 1.
1200    * @param k2 Key 2.
1201    * @param v2 Value 2.
1202    * @param k3 Key 3.
1203    * @param v3 Value 3.
1204    * @param k4 Key 4.
1205    * @param v4 Value 4.
1206    * @param k5 Key 5.
1207    * @param v5 Value 5.
1208    * @param k6 Key 6.
1209    * @param v6 Value 6.
1210    * @param k7 Key 7.
1211    * @param v7 Value 7.
1212    * @return A new unmodifiable map.
1213    */
1214   public static <K,V> Map<K,V> m(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) {
1215      return new SimpleMap<>(a(k1, k2, k3, k4, k5, k6, k7), a(v1, v2, v3, v4, v5, v6, v7));
1216   }
1217
1218   /**
1219    * Convenience method for creating an unmodifiable map.
1220    * Unlike Map.of(...), supports null keys/values and preserves insertion order.
1221    *
1222    * @param <K> The key type.
1223    * @param <V> The value type.
1224    * @param k1 Key 1.
1225    * @param v1 Value 1.
1226    * @param k2 Key 2.
1227    * @param v2 Value 2.
1228    * @param k3 Key 3.
1229    * @param v3 Value 3.
1230    * @param k4 Key 4.
1231    * @param v4 Value 4.
1232    * @param k5 Key 5.
1233    * @param v5 Value 5.
1234    * @param k6 Key 6.
1235    * @param v6 Value 6.
1236    * @param k7 Key 7.
1237    * @param v7 Value 7.
1238    * @param k8 Key 8.
1239    * @param v8 Value 8.
1240    * @return A new unmodifiable map.
1241    */
1242   public static <K,V> Map<K,V> m(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) {
1243      return new SimpleMap<>(a(k1, k2, k3, k4, k5, k6, k7, k8), a(v1, v2, v3, v4, v5, v6, v7, v8));
1244   }
1245
1246   /**
1247    * Convenience method for creating an unmodifiable map.
1248    * Unlike Map.of(...), supports null keys/values and preserves insertion order.
1249    *
1250    * @param <K> The key type.
1251    * @param <V> The value type.
1252    * @param k1 Key 1.
1253    * @param v1 Value 1.
1254    * @param k2 Key 2.
1255    * @param v2 Value 2.
1256    * @param k3 Key 3.
1257    * @param v3 Value 3.
1258    * @param k4 Key 4.
1259    * @param v4 Value 4.
1260    * @param k5 Key 5.
1261    * @param v5 Value 5.
1262    * @param k6 Key 6.
1263    * @param v6 Value 6.
1264    * @param k7 Key 7.
1265    * @param v7 Value 7.
1266    * @param k8 Key 8.
1267    * @param v8 Value 8.
1268    * @param k9 Key 9.
1269    * @param v9 Value 9.
1270    * @return A new unmodifiable map.
1271    */
1272   public static <K,V> Map<K,V> m(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) {
1273      return new SimpleMap<>(a(k1, k2, k3, k4, k5, k6, k7, k8, k9), a(v1, v2, v3, v4, v5, v6, v7, v8, v9));
1274   }
1275
1276   /**
1277    * Convenience method for creating an unmodifiable map.
1278    * Unlike Map.of(...), supports null keys/values and preserves insertion order.
1279    *
1280    * @param <K> The key type.
1281    * @param <V> The value type.
1282    * @param k1 Key 1.
1283    * @param v1 Value 1.
1284    * @param k2 Key 2.
1285    * @param v2 Value 2.
1286    * @param k3 Key 3.
1287    * @param v3 Value 3.
1288    * @param k4 Key 4.
1289    * @param v4 Value 4.
1290    * @param k5 Key 5.
1291    * @param v5 Value 5.
1292    * @param k6 Key 6.
1293    * @param v6 Value 6.
1294    * @param k7 Key 7.
1295    * @param v7 Value 7.
1296    * @param k8 Key 8.
1297    * @param v8 Value 8.
1298    * @param k9 Key 9.
1299    * @param v9 Value 9.
1300    * @param k10 Key 10.
1301    * @param v10 Value 10.
1302    * @return A new unmodifiable map.
1303    */
1304   public static <K,V> Map<K,V> m(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) {
1305      return new SimpleMap<>(a(k1, k2, k3, k4, k5, k6, k7, k8, k9, k10), a(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10));
1306   }
1307
1308   /**
1309    * Convenience method for creating a {@link LinkedHashMap}.
1310    *
1311    * @param <K> The key type.
1312    * @param <V> The value type.
1313    * @return A new modifiable map.
1314    */
1315   public static <K,V> LinkedHashMap<K,V> map() {
1316      var m = new LinkedHashMap<K,V>();
1317      return m;
1318   }
1319
1320   //-----------------------------------------------------------------------------------------------------------------
1321   // Array utilities
1322   //-----------------------------------------------------------------------------------------------------------------
1323
1324   /**
1325    * Convenience method for creating a {@link LinkedHashMap}.
1326    *
1327    * @param <K> The key type.
1328    * @param <V> The value type.
1329    * @param k1 Key 1.
1330    * @param v1 Value 1.
1331    * @return A new modifiable map.
1332    */
1333   public static <K,V> LinkedHashMap<K,V> map(K k1, V v1) {
1334      var m = new LinkedHashMap<K,V>();
1335      m.put(k1, v1);
1336      return m;
1337   }
1338
1339   /**
1340    * Convenience method for creating a {@link LinkedHashMap}.
1341    *
1342    * @param <K> The key type.
1343    * @param <V> The value type.
1344    * @param k1 Key 1.
1345    * @param v1 Value 1.
1346    * @param k2 Key 2.
1347    * @param v2 Value 2.
1348    * @return A new modifiable map.
1349    */
1350   public static <K,V> LinkedHashMap<K,V> map(K k1, V v1, K k2, V v2) {
1351      var m = new LinkedHashMap<K,V>();
1352      m.put(k1, v1);
1353      m.put(k2, v2);
1354      return m;
1355   }
1356
1357   /**
1358    * Convenience method for creating a {@link LinkedHashMap}.
1359    *
1360    * @param <K> The key type.
1361    * @param <V> The value type.
1362    * @param k1 Key 1.
1363    * @param v1 Value 1.
1364    * @param k2 Key 2.
1365    * @param v2 Value 2.
1366    * @param k3 Key 3.
1367    * @param v3 Value 3.
1368    * @return A new modifiable map.
1369    */
1370   public static <K,V> LinkedHashMap<K,V> map(K k1, V v1, K k2, V v2, K k3, V v3) {
1371      var m = new LinkedHashMap<K,V>();
1372      m.put(k1, v1);
1373      m.put(k2, v2);
1374      m.put(k3, v3);
1375      return m;
1376   }
1377
1378   /**
1379    * Convenience method for creating a {@link LinkedHashMap}.
1380    *
1381    * @param <K> The key type.
1382    * @param <V> The value type.
1383    * @param k1 Key 1.
1384    * @param v1 Value 1.
1385    * @param k2 Key 2.
1386    * @param v2 Value 2.
1387    * @param k3 Key 3.
1388    * @param v3 Value 3.
1389    * @param k4 Key 4.
1390    * @param v4 Value 4.
1391    * @return A new modifiable map.
1392    */
1393   public static <K,V> LinkedHashMap<K,V> map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
1394      var m = new LinkedHashMap<K,V>();
1395      m.put(k1, v1);
1396      m.put(k2, v2);
1397      m.put(k3, v3);
1398      m.put(k4, v4);
1399      return m;
1400   }
1401
1402   /**
1403    * Convenience method for creating a {@link LinkedHashMap}.
1404    *
1405    * @param <K> The key type.
1406    * @param <V> The value type.
1407    * @param k1 Key 1.
1408    * @param v1 Value 1.
1409    * @param k2 Key 2.
1410    * @param v2 Value 2.
1411    * @param k3 Key 3.
1412    * @param v3 Value 3.
1413    * @param k4 Key 4.
1414    * @param v4 Value 4.
1415    * @param k5 Key 5.
1416    * @param v5 Value 5.
1417    * @return A new modifiable map.
1418    */
1419   public static <K,V> LinkedHashMap<K,V> map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
1420      var m = new LinkedHashMap<K,V>();
1421      m.put(k1, v1);
1422      m.put(k2, v2);
1423      m.put(k3, v3);
1424      m.put(k4, v4);
1425      m.put(k5, v5);
1426      return m;
1427   }
1428
1429   /**
1430    * Convenience method for creating a {@link LinkedHashMap}.
1431    *
1432    * @param <K> The key type.
1433    * @param <V> The value type.
1434    * @param k1 Key 1.
1435    * @param v1 Value 1.
1436    * @param k2 Key 2.
1437    * @param v2 Value 2.
1438    * @param k3 Key 3.
1439    * @param v3 Value 3.
1440    * @param k4 Key 4.
1441    * @param v4 Value 4.
1442    * @param k5 Key 5.
1443    * @param v5 Value 5.
1444    * @param k6 Key 6.
1445    * @param v6 Value 6.
1446    * @return A new modifiable map.
1447    */
1448   public static <K,V> LinkedHashMap<K,V> map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) {
1449      var m = new LinkedHashMap<K,V>();
1450      m.put(k1, v1);
1451      m.put(k2, v2);
1452      m.put(k3, v3);
1453      m.put(k4, v4);
1454      m.put(k5, v5);
1455      m.put(k6, v6);
1456      return m;
1457   }
1458
1459   /**
1460    * Convenience method for creating a {@link LinkedHashMap}.
1461    *
1462    * @param <K> The key type.
1463    * @param <V> The value type.
1464    * @param k1 Key 1.
1465    * @param v1 Value 1.
1466    * @param k2 Key 2.
1467    * @param v2 Value 2.
1468    * @param k3 Key 3.
1469    * @param v3 Value 3.
1470    * @param k4 Key 4.
1471    * @param v4 Value 4.
1472    * @param k5 Key 5.
1473    * @param v5 Value 5.
1474    * @param k6 Key 6.
1475    * @param v6 Value 6.
1476    * @param k7 Key 7.
1477    * @param v7 Value 7.
1478    * @return A new modifiable map.
1479    */
1480   public static <K,V> LinkedHashMap<K,V> map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) {
1481      var m = new LinkedHashMap<K,V>();
1482      m.put(k1, v1);
1483      m.put(k2, v2);
1484      m.put(k3, v3);
1485      m.put(k4, v4);
1486      m.put(k5, v5);
1487      m.put(k6, v6);
1488      m.put(k7, v7);
1489      return m;
1490   }
1491
1492   /**
1493    * Convenience method for creating a {@link LinkedHashMap}.
1494    *
1495    * @param <K> The key type.
1496    * @param <V> The value type.
1497    * @param k1 Key 1.
1498    * @param v1 Value 1.
1499    * @param k2 Key 2.
1500    * @param v2 Value 2.
1501    * @param k3 Key 3.
1502    * @param v3 Value 3.
1503    * @param k4 Key 4.
1504    * @param v4 Value 4.
1505    * @param k5 Key 5.
1506    * @param v5 Value 5.
1507    * @param k6 Key 6.
1508    * @param v6 Value 6.
1509    * @param k7 Key 7.
1510    * @param v7 Value 7.
1511    * @param k8 Key 8.
1512    * @param v8 Value 8.
1513    * @return A new modifiable map.
1514    */
1515   public static <K,V> LinkedHashMap<K,V> map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) {
1516      var m = new LinkedHashMap<K,V>();
1517      m.put(k1, v1);
1518      m.put(k2, v2);
1519      m.put(k3, v3);
1520      m.put(k4, v4);
1521      m.put(k5, v5);
1522      m.put(k6, v6);
1523      m.put(k7, v7);
1524      m.put(k8, v8);
1525      return m;
1526   }
1527
1528   /**
1529    * Convenience method for creating a {@link LinkedHashMap}.
1530    *
1531    * @param <K> The key type.
1532    * @param <V> The value type.
1533    * @param k1 Key 1.
1534    * @param v1 Value 1.
1535    * @param k2 Key 2.
1536    * @param v2 Value 2.
1537    * @param k3 Key 3.
1538    * @param v3 Value 3.
1539    * @param k4 Key 4.
1540    * @param v4 Value 4.
1541    * @param k5 Key 5.
1542    * @param v5 Value 5.
1543    * @param k6 Key 6.
1544    * @param v6 Value 6.
1545    * @param k7 Key 7.
1546    * @param v7 Value 7.
1547    * @param k8 Key 8.
1548    * @param v8 Value 8.
1549    * @param k9 Key 9.
1550    * @param v9 Value 9.
1551    * @return A new modifiable map.
1552    */
1553   public static <K,V> LinkedHashMap<K,V> map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) {
1554      var m = new LinkedHashMap<K,V>();
1555      m.put(k1, v1);
1556      m.put(k2, v2);
1557      m.put(k3, v3);
1558      m.put(k4, v4);
1559      m.put(k5, v5);
1560      m.put(k6, v6);
1561      m.put(k7, v7);
1562      m.put(k8, v8);
1563      m.put(k9, v9);
1564      return m;
1565   }
1566
1567   /**
1568    * Convenience method for creating a {@link LinkedHashMap}.
1569    *
1570    * @param <K> The key type.
1571    * @param <V> The value type.
1572    * @param k1 Key 1.
1573    * @param v1 Value 1.
1574    * @param k2 Key 2.
1575    * @param v2 Value 2.
1576    * @param k3 Key 3.
1577    * @param v3 Value 3.
1578    * @param k4 Key 4.
1579    * @param v4 Value 4.
1580    * @param k5 Key 5.
1581    * @param v5 Value 5.
1582    * @param k6 Key 6.
1583    * @param v6 Value 6.
1584    * @param k7 Key 7.
1585    * @param v7 Value 7.
1586    * @param k8 Key 8.
1587    * @param v8 Value 8.
1588    * @param k9 Key 9.
1589    * @param v9 Value 9.
1590    * @param k10 Key 10.
1591    * @param v10 Value 10.
1592    * @return A new modifiable map.
1593    */
1594   public static <K,V> LinkedHashMap<K,V> map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) {
1595      var m = new LinkedHashMap<K,V>();
1596      m.put(k1, v1);
1597      m.put(k2, v2);
1598      m.put(k3, v3);
1599      m.put(k4, v4);
1600      m.put(k5, v5);
1601      m.put(k6, v6);
1602      m.put(k7, v7);
1603      m.put(k8, v8);
1604      m.put(k9, v9);
1605      m.put(k10, v10);
1606      return m;
1607   }
1608
1609   /**
1610    * Convenience factory for a {@link Maps} builder.
1611    *
1612    * <p>
1613    * This is a shortcut for <c>Maps.create().ordered()</c>.
1614    *
1615    * <h5 class='section'>Example:</h5>
1616    * <p class='bjava'>
1617    *    Map&lt;String,Object&gt; <jv>map</jv> = mapb()
1618    *       .add(<js>"foo"</js>, 1)
1619    *       .add(<js>"bar"</js>, 2)
1620    *       .build();
1621    * </p>
1622    *
1623    * @param <K> The key type.
1624    * @param <V> The value type.
1625    * @return A new map builder.
1626    * @see Maps
1627    */
1628   @SuppressWarnings("unchecked")
1629   public static <K,V> Maps<K,V> mapb() {
1630      return (Maps<K,V>)Maps.create().ordered();
1631   }
1632
1633   /**
1634    * Convenience factory for a {@link Maps} with {@link String} keys and {@link Object} values.
1635    *
1636    * <p>
1637    * This is a shortcut for <c>Maps.create(String.<jk>class</jk>, Object.<jk>class</jk>)</c>.
1638    *
1639    * <h5 class='section'>Example:</h5>
1640    * <p class='bjava'>
1641    *    Map&lt;String,Object&gt; <jv>map</jv> = mapb()
1642    *       .add(<js>"foo"</js>, 1)
1643    *       .add(<js>"bar"</js>, 2)
1644    *       .build();
1645    * </p>
1646    *
1647    * <p>
1648    * This builder supports optional filtering to automatically exclude unwanted values:
1649    * <p class='bjava'>
1650    *    <jc>// Build a map excluding null and empty values</jc>
1651    *    Map&lt;String,Object&gt; <jv>map</jv> = mapb().filtered()
1652    *       .add(<js>"foo"</js>, <jk>null</jk>)       <jc>// Excluded</jc>
1653    *       .add(<js>"bar"</js>, <js>""</js>)         <jc>// Excluded</jc>
1654    *       .add(<js>"baz"</js>, <js>"value"</js>)    <jc>// Included</jc>
1655    *       .build();
1656    * </p>
1657    *
1658    * @return A new map builder.
1659    * @see Maps
1660    */
1661   public static Maps<String,Object> mapb_so() {
1662      return Maps.create(String.class, Object.class).ordered();
1663   }
1664
1665   /**
1666    * Convenience factory for a filtered, sorted, fluent map with {@link String} keys and {@link Object} values.
1667    *
1668    * <p>
1669    * This is a shortcut for <c>Maps.create(String.<jk>class</jk>, Object.<jk>class</jk>).filtered().sorted().buildFluent()</c>.
1670    *
1671    * <p>
1672    * This is typically used for creating property maps in <c>toString()</c> methods that need to be sorted and filtered.
1673    *
1674    * <h5 class='section'>Example:</h5>
1675    * <p class='bjava'>
1676    *    <jc>// In a properties() method</jc>
1677    *    <jk>return</jk> filteredBeanPropertyMap()
1678    *       .a(<js>"name"</js>, <jv>name</jv>)
1679    *       .a(<js>"value"</js>, <jv>value</jv>);
1680    * </p>
1681    *
1682    * @return A new filtered, sorted, fluent map builder.
1683    * @see FluentMap
1684    * @see Maps
1685    */
1686   public static FluentMap<String,Object> filteredBeanPropertyMap() {
1687      return Maps.create(String.class, Object.class).filtered().sorted().buildFluent();
1688   }
1689
1690   /**
1691    * Convenience factory for a {@link Maps}.
1692    *
1693    * @param <K> The key type.
1694    * @param <V> The value type.
1695    * @param keyType The key type.
1696    * @param valueType The value type.
1697    * @return A new map builder.
1698    */
1699   public static <K,V> Maps<K,V> mapb(Class<K> keyType, Class<V> valueType) {
1700      return Maps.create(keyType, valueType).ordered();
1701   }
1702
1703   /**
1704    * Shortcut for creating an empty map of the specified types.
1705    *
1706    * @param <K> The key type.
1707    * @param <V> The value type.
1708    * @param keyType The key type class.
1709    * @param valueType The value type class.
1710    * @return An empty unmodifiable map.
1711    */
1712   public static <K,V> Map<K,V> mape(Class<K> keyType, Class<V> valueType) {
1713      return Collections.emptyMap();
1714   }
1715
1716   /**
1717    * Shortcut for creating an empty map with generic types.
1718    *
1719    * <p>
1720    * This is a convenience method that creates an empty unmodifiable map without requiring
1721    * explicit type parameters. The types will be inferred from usage context.
1722    *
1723    * @param <K> The key type.
1724    * @param <V> The value type.
1725    * @return An empty unmodifiable map.
1726    */
1727   public static <K,V> Map<K,V> mape() {
1728      return Collections.emptyMap();
1729   }
1730   /**
1731    * Returns a null map.
1732    *
1733    * @param <K> The key type.
1734    * @param <V> The value type.
1735    * @param keyType The key type class.
1736    * @param valueType The value type class.
1737    * @return <jk>null</jk>.
1738    */
1739   public static <K,V> Map<K,V> mapn(Class<K> keyType, Class<V> valueType) {
1740      return null;
1741   }
1742
1743   /**
1744    * Convenience method for creating a {@link LinkedHashMap}.
1745    *
1746    * @param <K> The key type.
1747    * @param <V> The value type.
1748    * @param keyType The key type.
1749    * @param valueType The value type.
1750    * @return A new modifiable map.
1751    */
1752   public static <K,V> LinkedHashMap<K,V> mapOf(Class<K> keyType, Class<V> valueType) {
1753      return map();
1754   }
1755
1756   /**
1757    * Returns <jk>null</jk> for the specified array type.
1758    *
1759    * @param <T> The component type.
1760    * @param type The component type class.
1761    * @return <jk>null</jk>.
1762    */
1763   public static <T> T[] na(Class<T> type) {
1764      return null;
1765   }
1766
1767   /**
1768    * Adds all the specified values to the specified collection.
1769    * Creates a new set if the value is <jk>null</jk>.
1770    *
1771    * @param <E> The element type.
1772    * @param value The collection to add to.
1773    * @param entries The entries to add.
1774    * @return The set.
1775    */
1776   @SafeVarargs
1777   public static <E> List<E> prependAll(List<E> value, E...entries) {
1778      if (nn(entries)) {
1779         if (value == null)
1780            value = list(entries);
1781         else
1782            value.addAll(0, l(entries));
1783      }
1784      return value;
1785   }
1786
1787   /**
1788    * Reverses the entries in an array.
1789    *
1790    * @param <E> The element type.
1791    * @param array The array to reverse.
1792    * @return The same array.
1793    */
1794   /**
1795    * Reverses the elements in the specified array in-place.
1796    *
1797    * @param <E> The element type.
1798    * @param array The array to reverse.
1799    * @return The same array, reversed.
1800    */
1801   public static <E> E[] reverse(E[] array) {
1802      for (var i = 0; i < array.length / 2; i++) {
1803         E temp = array[i];
1804         array[i] = array[array.length - i - 1];
1805         array[array.length - i - 1] = temp;
1806      }
1807      return array;
1808   }
1809
1810   /**
1811    * Returns a reversed view of the specified list.
1812    *
1813    * <p>
1814    * The returned list is a live view that reflects changes to the original list.
1815    *
1816    * @param <E> The element type.
1817    * @param list The list to reverse.
1818    * @return A reversed view of the list.
1819    */
1820   public static <E> List<E> reverse(List<E> list) {
1821      return new ReversedList<>(list);
1822   }
1823
1824   /**
1825    * Returns a reverse stream of the specified list.
1826    *
1827    * <h5 class='section'>Example:</h5>
1828    * <p class='bjava'>
1829    *    List&lt;String&gt; <jv>list</jv> = <jsm>list</jsm>(<js>"a"</js>, <js>"b"</js>, <js>"c"</js>);
1830    *    Stream&lt;String&gt; <jv>reversed</jv> = <jsm>rstream</jsm>(<jv>list</jv>);
1831    *    <jc>// Produces stream: "c", "b", "a"</jc>
1832    * </p>
1833    *
1834    * @param <T> The element type.
1835    * @param value The list to stream in reverse order. Can be <jk>null</jk>.
1836    * @return A stream of the list elements in reverse order, or an empty stream if the list is <jk>null</jk> or empty.
1837    */
1838   public static <T> Stream<T> rstream(List<T> value) {
1839      if (value == null || value.isEmpty())
1840         return Stream.empty();
1841      return IntStream.range(0, value.size()).mapToObj(i -> value.get(value.size() - 1 - i));
1842   }
1843
1844   /**
1845    * Shortcut for creating a modifiable set out of an array of values.
1846    *
1847    * @param <T> The element type.
1848    * @param values The values to add to the set.
1849    * @return A modifiable LinkedHashSet containing the specified values.
1850    */
1851   @SafeVarargs
1852   public static <T> LinkedHashSet<T> set(T...values) {  // NOSONAR
1853      assertArgNotNull("values", values);
1854      return new LinkedHashSet<>(Arrays.asList(values));
1855   }
1856
1857   /**
1858    * Returns an empty immutable set.
1859    *
1860    * <p>
1861    * This is a convenience method that returns {@link Collections#emptySet()}.
1862    *
1863    * <h5 class='section'>Example:</h5>
1864    * <p class='bjava'>
1865    *    Set&lt;String&gt; <jv>empty</jv> = CollectionUtils.<jsf>sete</jsf>();  <jc>// Returns Collections.emptySet()</jc>
1866    * </p>
1867    *
1868    * @param <T> The element type.
1869    * @return An empty immutable set.
1870    * @see Collections#emptySet()
1871    */
1872   public static <T> Set<T> sete() {
1873      return Collections.emptySet();
1874   }
1875
1876   /**
1877    * Convenience factory for a {@link Sets}.
1878    *
1879    * @param <E> The element type.
1880    * @param type The element type.
1881    * @return A new set builder.
1882    */
1883   public static <E> Sets<E> setb(Class<E> type) {
1884      return Sets.create(type).ordered();
1885   }
1886
1887   /**
1888    * Convenience method for creating a {@link LinkedHashSet}.
1889    *
1890    * @param <E> The element type.
1891    * @param elementType The element type.
1892    * @param values The values to initialize the set with.
1893    * @return A new modifiable set.
1894    */
1895   @SafeVarargs
1896   public static <E> LinkedHashSet<E> setOf(Class<E> elementType, E...values) {
1897      return set(values);
1898   }
1899
1900   /**
1901    * Shortcut for creating a short array.
1902    *
1903    * <p>Accepts int values and converts them to shorts, eliminating the need for explicit short casts.</p>
1904    *
1905    * <h5 class='section'>Example:</h5>
1906    * <p class='bjava'>
1907    *    <jk>short</jk>[] <jv>myArray</jv> = <jsm>shorts</jsm>(1, 2, 3);
1908    * </p>
1909    *
1910    * @param value The int values to convert to shorts. Values outside the short range (-32768 to 32767) will be truncated.
1911    * @return A new short array.
1912    */
1913   public static short[] shorts(int...value) {
1914      var result = new short[value.length];
1915      for (var i = 0; i < value.length; i++) {
1916         result[i] = (short)value[i];
1917      }
1918      return result;
1919   }
1920
1921   /**
1922    * Convenience method for creating an {@link ArrayList} and sorting it.
1923    *
1924    * @param <E> The element type.
1925    * @param comparator The comparator to use to sort the list.
1926    * @param value The values to initialize the list with.
1927    * @return A new modifiable list.
1928    */
1929   public static <E> ArrayList<E> sortedList(Comparator<E> comparator, Collection<E> value) {
1930      ArrayList<E> l = toList(value);
1931      Collections.sort(l, comparator);
1932      return l;
1933   }
1934
1935   /**
1936    * Convenience method for creating an {@link ArrayList} and sorting it.
1937    *
1938    * @param <E> The element type.
1939    * @param comparator The comparator to use to sort the list.
1940    * @param values The values to initialize the list with.
1941    * @return A new modifiable list.
1942    */
1943   public static <E> List<E> sortedList(Comparator<E> comparator, E[] values) {
1944      List<E> l = list(values);
1945      Collections.sort(l, comparator);
1946      return l;
1947   }
1948
1949   /**
1950    * Convenience method for creating an {@link ArrayList} and sorting it.
1951    *
1952    * @param <E> The element type.
1953    * @param values The values to initialize the list with.
1954    * @return A new modifiable list.
1955    */
1956   @SuppressWarnings({ "rawtypes", "unchecked" })
1957   @SafeVarargs
1958   public static <E> List<E> sortedList(E...values) {
1959      List<E> l = list(values);
1960      Collections.sort((List<Comparable>)l);
1961      return l;
1962   }
1963
1964   /**
1965    * Convenience method for creating a {@link TreeMap}.
1966    *
1967    * @param <K> The key type.
1968    * @param <V> The value type.
1969    * @return A new modifiable set.
1970    */
1971   public static <K,V> TreeMap<K,V> sortedMap() {
1972      return new TreeMap<>();
1973   }
1974
1975   /**
1976    * Convenience method for creating a {@link TreeSet}.
1977    *
1978    * <p>
1979    * Note: <jk>null</jk> values in the varargs array are automatically filtered out
1980    * because {@link TreeSet} does not support <jk>null</jk> elements.
1981    *
1982    * @param <E> The element type.
1983    * @param values The values to initialize the set with.
1984    *    <br>Can contain <jk>null</jk> values (they will be filtered out).
1985    * @return A new modifiable set.
1986    */
1987   @SafeVarargs
1988   public static <E> TreeSet<E> sortedSet(E...values) {
1989      assertArgNotNull("values", values);
1990      var l = new TreeSet<E>();
1991      for (var v : values)
1992         if (v != null)
1993            l.add(v);
1994      return l;
1995   }
1996
1997   /**
1998    * Returns a stream of the specified array.
1999    *
2000    * <p>
2001    * Gracefully handles <jk>null</jk> arrays by returning an empty stream.
2002    *
2003    * <h5 class='section'>Example:</h5>
2004    * <p class='bjava'>
2005    *    String[] <jv>array</jv> = {<js>"a"</js>, <js>"b"</js>, <js>"c"</js>};
2006    *
2007    *    <jc>// Prints "a", "b", "c"</jc>
2008    *    <jsm>stream</jsm>(<jv>array</jv>).forEach(System.<jk>out</jk>::println);
2009    *
2010    *    <jc>// Handles null gracefully - returns empty stream</jc>
2011    *    <jsm>stream</jsm>(<jk>null</jk>).forEach(System.<jk>out</jk>::println);  <jc>// Prints nothing</jc>
2012    * </p>
2013    *
2014    * @param <T> The element type.
2015    * @param array The array to stream. Can be <jk>null</jk>.
2016    * @return A stream of the array elements, or an empty stream if the array is <jk>null</jk>.
2017    */
2018   public static <T> Stream<T> stream(T[] array) {
2019      return array == null ? Stream.empty() : Arrays.stream(array);
2020   }
2021
2022   /**
2023    * Wraps the specified list in {@link Collections#unmodifiableList(List)}.
2024    *
2025    * @param <E> The element type.
2026    * @param value The list to wrap.
2027    * @return The wrapped list.
2028    */
2029   public static <E> List<E> synced(List<E> value) {
2030      return value == null ? null : Collections.synchronizedList(value);
2031   }
2032
2033   /**
2034    * Wraps the specified map in {@link Collections#unmodifiableMap(Map)}.
2035    *
2036    * @param <K> The key type.
2037    * @param <V> The value type.
2038    * @param value The map to wrap.
2039    * @return The wrapped map.
2040    */
2041   public static <K,V> Map<K,V> synced(Map<K,V> value) {
2042      return value == null ? null : Collections.synchronizedMap(value);
2043   }
2044
2045   /**
2046    * Wraps the specified set in {@link Collections#unmodifiableSet(Set)}.
2047    *
2048    * @param <E> The element type.
2049    * @param value The set to wrap.
2050    * @return The wrapped set.
2051    */
2052   public static <E> Set<E> synced(Set<E> value) {
2053      return value == null ? null : Collections.synchronizedSet(value);
2054   }
2055
2056   /**
2057    * Converts the specified collection to an array.
2058    *
2059    * <p>
2060    * Works on both object and primitive arrays.
2061    *
2062    * @param <E> The element type.
2063    * @param c The collection to convert to an array.
2064    * @param elementType The component type of the collection.
2065    * @return A new array.
2066    */
2067   public static <E> Object toArray(Collection<?> c, Class<E> elementType) {
2068      var a = Array.newInstance(elementType, c.size());
2069      Iterator<?> it = c.iterator();
2070      int i = 0;
2071      while (it.hasNext())
2072         Array.set(a, i++, it.next());
2073      return a;
2074   }
2075
2076   /**
2077    * Creates an {@link ArrayList} copy from a collection.
2078    *
2079    * @param <E> The element type.
2080    * @param value The collection to copy from.
2081    * @return A new modifiable list.
2082    */
2083   public static <E> ArrayList<E> toList(Collection<E> value) {
2084      return toList(value, false);
2085   }
2086
2087   /**
2088    * Creates an {@link ArrayList} copy from a collection.
2089    *
2090    * @param <E> The element type.
2091    * @param value The collection to copy from.
2092    * @param nullIfEmpty If <jk>true</jk> will return <jk>null</jk> if the collection is empty.
2093    * @return A new modifiable list.
2094    */
2095   public static <E> ArrayList<E> toList(Collection<E> value, boolean nullIfEmpty) {
2096      if (value == null || (nullIfEmpty && value.isEmpty()))
2097         return null;
2098      var l = new ArrayList<E>();
2099      value.forEach(x -> l.add(x));
2100      return l;
2101   }
2102
2103   /**
2104    * Converts various collection-like objects to a {@link List}.
2105    *
2106    * <p>This utility method enables testing of any collection-like object by converting it to a List that can be
2107    * passed to methods such as TestUtils.assertList().</p>
2108    *
2109    * <h5 class='section'>Supported Input Types:</h5>
2110    * <ul>
2111    *    <li><b>List:</b> Returns the input unchanged</li>
2112    *    <li><b>Iterable:</b> Any collection, set, queue, etc. (converted to List preserving order)</li>
2113    *    <li><b>Iterator:</b> Converts iterator contents to List</li>
2114    *    <li><b>Enumeration:</b> Converts enumeration contents to List</li>
2115    *    <li><b>Stream:</b> Converts stream contents to List (stream is consumed)</li>
2116    *    <li><b>Map:</b> Converts map entries to List of Map.Entry objects</li>
2117    *    <li><b>Array:</b> Converts any array type (including primitive arrays) to List</li>
2118    * </ul>
2119    *
2120    * <h5 class='section'>Usage Examples:</h5>
2121    * <p class='bjava'>
2122    *    <jc>// Test a Set</jc>
2123    *    Set&lt;String&gt; <jv>mySet</jv> = Set.of(<js>"a"</js>, <js>"b"</js>, <js>"c"</js>);
2124    *    assertList(toList(<jv>mySet</jv>), <js>"a"</js>, <js>"b"</js>, <js>"c"</js>);
2125    *
2126    *    <jc>// Test an array</jc>
2127    *    String[] <jv>myArray</jv> = {<js>"x"</js>, <js>"y"</js>, <js>"z"</js>};
2128    *    assertList(toList(<jv>myArray</jv>), <js>"x"</js>, <js>"y"</js>, <js>"z"</js>);
2129    *
2130    *    <jc>// Test a primitive array</jc>
2131    *    <jk>int</jk>[] <jv>numbers</jv> = {1, 2, 3};
2132    *    assertList(toList(<jv>numbers</jv>), <js>"1"</js>, <js>"2"</js>, <js>"3"</js>);
2133    *
2134    *    <jc>// Test a Stream</jc>
2135    *    Stream&lt;String&gt; <jv>myStream</jv> = Stream.of(<js>"foo"</js>, <js>"bar"</js>);
2136    *    assertList(toList(<jv>myStream</jv>), <js>"foo"</js>, <js>"bar"</js>);
2137    *
2138    *    <jc>// Test a Map (converted to entries)</jc>
2139    *    Map&lt;String,Integer&gt; <jv>myMap</jv> = Map.of(<js>"a"</js>, 1, <js>"b"</js>, 2);
2140    *    assertList(toList(<jv>myMap</jv>), <js>"a=1"</js>, <js>"b=2"</js>);
2141    *
2142    *    <jc>// Test any Iterable collection</jc>
2143    *    Queue&lt;String&gt; <jv>myQueue</jv> = new LinkedList&lt;&gt;(List.of(<js>"first"</js>, <js>"second"</js>));
2144    *    assertList(toList(<jv>myQueue</jv>), <js>"first"</js>, <js>"second"</js>);
2145    * </p>
2146    *
2147    * <h5 class='section'>Integration with Testing:</h5>
2148    * <p>This method is specifically designed to work with testing frameworks to provide
2149    * a unified testing approach for all collection-like types. Instead of having separate assertion methods
2150    * for arrays, sets, and other collections, you can convert them all to Lists and use standard
2151    * list assertion methods.</p>
2152    *
2153    * @param o The object to convert to a List. Must not be null and must be a supported collection-like type.
2154    * @return A {@link List} containing the elements from the input object.
2155    * @throws IllegalArgumentException if the input object cannot be converted to a List.
2156    * @see arrayToList
2157    */
2158   public static final List<?> toList(Object o) {  // NOSONAR
2159      assertArgNotNull("o", o);
2160      if (o instanceof List<?> o2)
2161         return o2;
2162      if (o instanceof Iterable<?> o2)
2163         return StreamSupport.stream(o2.spliterator(), false).toList();
2164      if (o instanceof Iterator<?> o2)
2165         return StreamSupport.stream(Spliterators.spliteratorUnknownSize(o2, 0), false).toList();
2166      if (o instanceof Enumeration<?> o2)
2167         return Collections.list(o2);
2168      if (o instanceof Stream<?> o2)
2169         return o2.toList();
2170      if (o instanceof Map<?,?> o2)
2171         return toList(o2.entrySet());
2172      if (o instanceof Optional<?> o2)
2173         return o2.isEmpty() ? Collections.emptyList() : Collections.singletonList(o2.get());
2174      if (isArray(o))
2175         return arrayToList(o);
2176      throw rex("Could not convert object of type {0} to a list", cn(o));
2177   }
2178
2179   /**
2180    * Converts the specified array to an <c>ArrayList</c>
2181    *
2182    * @param <E> The element type.
2183    * @param array The array to convert.
2184    * @param elementType
2185    *    The type of objects in the array.
2186    *    It must match the actual component type in the array.
2187    * @return A new {@link ArrayList}
2188    */
2189   @SuppressWarnings("unchecked")
2190   public static <E> List<E> toList(Object array, Class<E> elementType) {
2191      var l = new ArrayList<E>(Array.getLength(array));
2192      for (var i = 0; i < Array.getLength(array); i++)
2193         l.add((E)Array.get(array, i));
2194      return l;
2195   }
2196
2197   /**
2198    * Recursively converts the specified array into a list of objects.
2199    *
2200    * @param array The array to convert.
2201    * @return A new {@link ArrayList}
2202    */
2203   public static List<Object> toObjectList(Object array) {
2204      var l = new ArrayList<>(Array.getLength(array));
2205      for (var i = 0; i < Array.getLength(array); i++) {
2206         var o = Array.get(array, i);
2207         if (isArray(o))
2208            o = toObjectList(o);
2209         l.add(o);
2210      }
2211      return l;
2212   }
2213
2214   /**
2215    * Creates a new set from the specified collection.
2216    *
2217    * @param <E> The element type.
2218    * @param val The value to copy from.
2219    * @return A new {@link LinkedHashSet}, or <jk>null</jk> if the input was null.
2220    */
2221   public static <E> Set<E> toSet(Collection<E> val) {
2222      return val == null ? null : new LinkedHashSet<>(val);
2223   }
2224
2225   /**
2226    * Converts the specified array to a <c>Set</c>.
2227    *
2228    * <p>
2229    * The order of the entries in the set are the same as the array.
2230    *
2231    * @param <T> The entry type of the array.
2232    * @param array The array being wrapped in a <c>Set</c> interface.
2233    * @return The new set.
2234    */
2235   public static <T> Set<T> toSet(T[] array) {
2236      assertArgNotNull("array", array);
2237      return new AbstractSet<>() {
2238
2239         @Override /* Overridden from Set */
2240         public Iterator<T> iterator() {
2241            return new Iterator<>() {
2242               int i = 0;
2243
2244               @Override /* Overridden from Iterator */
2245               public boolean hasNext() {
2246                  return i < array.length;
2247               }
2248
2249               @Override /* Overridden from Iterator */
2250               public T next() {
2251                  if (i >= array.length)
2252                     throw new NoSuchElementException();
2253                  T t = array[i];
2254                  i++;
2255                  return t;
2256               }
2257
2258               @Override /* Overridden from Iterator */
2259               public void remove() {
2260                  throw unsupportedOp();
2261               }
2262            };
2263         }
2264
2265         @Override /* Overridden from Set */
2266         public int size() {
2267            return array.length;
2268         }
2269      };
2270   }
2271
2272   //-----------------------------------------------------------------------------------------------------------------
2273   // Primitive array creation methods
2274   //-----------------------------------------------------------------------------------------------------------------
2275
2276   /**
2277    * Creates a new {@link TreeSet} from the specified collection.
2278    *
2279    * @param <E> The element type.
2280    * @param value The value to copy from.
2281    * @return A new {@link TreeSet}, or <jk>null</jk> if the input was null.
2282    */
2283   public static <E> TreeSet<E> toSortedSet(Collection<E> value) {
2284      if (value == null)
2285         return null;
2286      var l = new TreeSet<E>();
2287      value.forEach(x -> l.add(x));
2288      return l;
2289   }
2290
2291   /**
2292    * Creates a new {@link TreeSet} from the specified collection.
2293    *
2294    * @param <E> The element type.
2295    * @param value The value to copy from.
2296    * @param nullIfEmpty If <jk>true</jk> returns <jk>null</jk> if the collection is empty.
2297    * @return A new {@link TreeSet}, or <jk>null</jk> if the input was null.
2298    */
2299   public static <E> TreeSet<E> toSortedSet(Collection<E> value, boolean nullIfEmpty) {
2300      if (value == null || (nullIfEmpty && value.isEmpty()))
2301         return null;
2302      var l = new TreeSet<E>();
2303      value.forEach(x -> l.add(x));
2304      return l;
2305   }
2306
2307   /**
2308    * Creates a new {@link TreeSet} containing a copy of the specified set.
2309    *
2310    * @param <T> The element type.
2311    * @param copyFrom The set to copy from.
2312    * @return A new {@link TreeSet}, or <jk>null</jk> if the set was <jk>null</jk>.
2313    */
2314   public static <T> TreeSet<T> toSortedSet(Set<T> copyFrom) {
2315      return copyFrom == null ? null : new TreeSet<>(copyFrom);
2316   }
2317
2318   /**
2319    * Converts an array to a stream of objects.
2320    * @param array The array to convert.
2321    * @return A new stream.
2322    */
2323   public static Stream<Object> toStream(Object array) {
2324      assertArg(isArray(array), "Arg was not an array.  Type: {0}", cn(array));
2325      var length = Array.getLength(array);
2326      return IntStream.range(0, length).mapToObj(i -> Array.get(array, i));
2327   }
2328
2329   /**
2330    * Converts the specified collection to an array of strings.
2331    *
2332    * <p>
2333    * Entries are converted to strings using {@link #toString()}.
2334    * <jk>null</jk> values remain <jk>null</jk>.
2335    *
2336    * @param c The collection to convert.
2337    * @return The collection as a string array.
2338    */
2339   public static String[] toStringArray(Collection<?> c) {
2340      var r = new String[c.size()];
2341      var i = 0;
2342      for (var o : c)
2343         r[i++] = s(o);
2344      return r;
2345   }
2346
2347   /**
2348    * Traverses all elements in the specified object and executes a consumer for it.
2349    *
2350    * @param <T> The element type.
2351    * @param o The object to traverse.
2352    * @param c The consumer of the objects.
2353    */
2354   @SuppressWarnings("unchecked")
2355   public static <T> void traverse(Object o, Consumer<T> c) {
2356      if (o == null)
2357         return;
2358      if (o instanceof Iterable<?> o2)
2359         o2.forEach(x -> traverse(x, c));
2360      else if (o instanceof Stream<?> o2)
2361         o2.forEach(x -> traverse(x, c));
2362      else if (isArray(o))
2363         toStream(o).forEach(x -> traverse(x, c));
2364      else
2365         c.accept((T)o);
2366   }
2367
2368   /**
2369    * Creates an unmodifiable view of the specified list.
2370    *
2371    * <p>This is a null-safe wrapper around {@link Collections#unmodifiableList(List)}.</p>
2372    *
2373    * @param <T> The element type.
2374    * @param value The list to make unmodifiable. Can be null.
2375    * @return An unmodifiable view of the list, or null if the input was null.
2376    */
2377   public static <T> List<T> u(List<? extends T> value) {
2378      return value == null ? null : Collections.unmodifiableList(value);
2379   }
2380
2381   /**
2382    * Creates an unmodifiable view of the specified map.
2383    *
2384    * <p>This is a null-safe wrapper around {@link Collections#unmodifiableMap(Map)}.</p>
2385    *
2386    * @param <K> The key type.
2387    * @param <V> The value type.
2388    * @param value The map to make unmodifiable. Can be null.
2389    * @return An unmodifiable view of the map, or null if the input was null.
2390    */
2391   public static <K,V> Map<K,V> u(Map<? extends K,? extends V> value) {
2392      return value == null ? null : Collections.unmodifiableMap(value);
2393   }
2394
2395   //-----------------------------------------------------------------------------------------------------------------
2396   // Stream utilities
2397   //-----------------------------------------------------------------------------------------------------------------
2398
2399   /**
2400    * Creates an unmodifiable view of the specified set.
2401    *
2402    * <p>This is a null-safe wrapper around {@link Collections#unmodifiableSet(Set)}.</p>
2403    *
2404    * @param <T> The element type.
2405    * @param value The set to make unmodifiable. Can be null.
2406    * @return An unmodifiable view of the set, or null if the input was null.
2407    */
2408   public static <T> Set<T> u(Set<? extends T> value) {
2409      return value == null ? null : Collections.unmodifiableSet(value);
2410   }
2411
2412   private CollectionUtils() {}
2413}