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<Map<String,Object>>[] <jv>data</jv> = <jk>new</jk> List[]{ 057 * <jk>new</jk> ArrayList<>(Arrays.asList( 058 * <jk>new</jk> LinkedHashMap<>(){{ 059 * put(<js>"name"</js>, <js>"John"</js>); 060 * put(<js>"age"</js>, 30); 061 * }} 062 * )), 063 * <jk>new</jk> ArrayList<>(Arrays.asList( 064 * <jk>new</jk> LinkedHashMap<>(){{ 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<Map<String,Object>>[] <jv>complex</jv> = <jk>new</jk> List[]{ 086 * <jk>new</jk> ArrayList<>(Arrays.asList( 087 * <jk>new</jk> LinkedHashMap<>(){{ 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<>(){{ 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<>(Arrays.asList( 097 * <jk>new</jk> LinkedHashMap<>(){{ 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<String> <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<String> <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<String> <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<String> <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<String> <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<String,Object> <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<String,Object> <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<String,Object> <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<String> <jv>list</jv> = <jsm>list</jsm>(<js>"a"</js>, <js>"b"</js>, <js>"c"</js>); 1830 * Stream<String> <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<String> <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<String> <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<String> <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<String,Integer> <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<String> <jv>myQueue</jv> = new LinkedList<>(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}