001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.internal; 014 015import java.lang.reflect.*; 016import java.util.*; 017import java.util.function.*; 018 019/** 020 * Utility methods for collections. 021 * 022 * <h5 class='section'>See Also:</h5><ul> 023 024 * </ul> 025 */ 026public final class CollectionUtils { 027 028 /** 029 * Creates a new set from the specified collection. 030 * 031 * @param <E> The element type. 032 * @param val The value to copy from. 033 * @return A new {@link LinkedHashSet}, or <jk>null</jk> if the input was null. 034 */ 035 public static <E> Set<E> setFrom(Collection<E> val) { 036 return val == null ? null : new LinkedHashSet<>(val); 037 } 038 039 /** 040 * Creates a new set from the specified collection. 041 * 042 * @param <E> The element type. 043 * @param val The value to copy from. 044 * @return A new {@link LinkedHashSet}, or <jk>null</jk> if the input was null. 045 */ 046 public static <E> Set<E> copyOf(Set<E> val) { 047 return val == null ? null : new LinkedHashSet<>(val); 048 } 049 050 /** 051 * Creates a new collection from the specified collection. 052 * 053 * @param <E> The element type. 054 * @param val The value to copy from. 055 * @return A new {@link LinkedHashSet}, or <jk>null</jk> if the input was null. 056 */ 057 public static <E> Collection<E> copyOf(Collection<E> val) { 058 return val == null ? null : new LinkedHashSet<>(val); 059 } 060 061 /** 062 * Creates a new map from the specified map. 063 * 064 * @param <K> The key type. 065 * @param <V> The value type. 066 * @param val The value to copy from. 067 * @return A new {@link LinkedHashMap}, or <jk>null</jk> if the input was null. 068 */ 069 public static <K,V> Map<K,V> copyOf(Map<K,V> val) { 070 return val == null ? null : new LinkedHashMap<>(val); 071 } 072 073 /** 074 * Instantiates a new builder on top of the specified map. 075 * 076 * @param <K> The key type. 077 * @param <V> The value type. 078 * @param addTo The map to add to. 079 * @return A new builder on top of the specified map. 080 */ 081 public static <K,V> MapBuilder<K,V> mapBuilder(Map<K,V> addTo) { 082 return new MapBuilder<>(addTo); 083 } 084 085 /** 086 * Instantiates a new builder of the specified map type. 087 * 088 * @param <K> The key type. 089 * @param <V> The value type. 090 * @param keyType The key type. 091 * @param valueType The value type. 092 * @param valueTypeArgs The value type args. 093 * @return A new builder on top of the specified map. 094 */ 095 public static <K,V> MapBuilder<K,V> mapBuilder(Class<K> keyType, Class<V> valueType, Type...valueTypeArgs) { 096 return new MapBuilder<>(keyType, valueType, valueTypeArgs); 097 } 098 099 /** 100 * Instantiates a new builder on top of the specified list. 101 * 102 * @param <E> The element type. 103 * @param addTo The list to add to. 104 * @return A new builder on top of the specified list. 105 */ 106 public static <E> ListBuilder<E> listBuilder(List<E> addTo) { 107 return new ListBuilder<>(addTo); 108 } 109 110 /** 111 * Instantiates a new builder of the specified list type. 112 * 113 * @param <E> The element type. 114 * @param elementType The element type. 115 * @param elementTypeArgs The element type args. 116 * @return A new builder on top of the specified list. 117 */ 118 public static <E> ListBuilder<E> listBuilder(Class<E> elementType, Type...elementTypeArgs) { 119 return new ListBuilder<>(elementType, elementTypeArgs); 120 } 121 122 /** 123 * Instantiates a new builder on top of the specified set. 124 * 125 * @param <E> The element type. 126 * @param addTo The set to add to. 127 * @return A new builder on top of the specified set. 128 */ 129 public static <E> SetBuilder<E> setBuilder(Set<E> addTo) { 130 return new SetBuilder<>(addTo); 131 } 132 133 /** 134 * Instantiates a new builder of the specified set. 135 * 136 * @param <E> The element type. 137 * @param elementType The element type. 138 * @param elementTypeArgs The element type args. 139 * @return A new builder on top of the specified set. 140 */ 141 public static <E> SetBuilder<E> setBuilder(Class<E> elementType, Type...elementTypeArgs) { 142 return new SetBuilder<>(elementType, elementTypeArgs); 143 } 144 145 /** 146 * Simple passthrough to {@link Collections#emptyList()} 147 * 148 * @param <E> The element type. 149 * @return A new unmodifiable empty list. 150 */ 151 public static <E> List<E> emptyList() { 152 return Collections.emptyList(); 153 } 154 155 /** 156 * Convenience method for creating an {@link ArrayList}. 157 * 158 * @param <E> The element type. 159 * @param values The values to initialize the list with. 160 * @return A new modifiable list. 161 */ 162 @SafeVarargs 163 public static <E> ArrayList<E> list(E...values) { 164 ArrayList<E> l = new ArrayList<>(values.length); 165 for (E v : values) 166 l.add(v); 167 return l; 168 } 169 170 /** 171 * Convenience method for creating an {@link ArrayList} of the specified size. 172 * 173 * @param <E> The element type. 174 * @param size The initial size of the list. 175 * @return A new modifiable list. 176 */ 177 public static <E> ArrayList<E> list(int size) { 178 return new ArrayList<>(size); 179 } 180 181 /** 182 * Convenience method for creating a {@link LinkedList}. 183 * 184 * @param <E> The element type. 185 * @param values The values to initialize the list with. 186 * @return A new modifiable list. 187 */ 188 @SafeVarargs 189 public static <E> LinkedList<E> linkedList(E...values) { 190 LinkedList<E> l = new LinkedList<>(); 191 for (E v : values) 192 l.add(v); 193 return l; 194 } 195 196 /** 197 * Convenience method for creating an array-backed list by calling {@link Arrays#asList(Object...)}. 198 * 199 * @param <E> The element type. 200 * @param values The values to initialize the list with. 201 * @return A new modifiable list, or <jk>null</jk> if the array was <jk>null</jk>. 202 */ 203 @SafeVarargs 204 public static <E> List<E> alist(E...values) { 205 if (values == null) 206 return null; 207 return Arrays.asList(values); 208 } 209 210 /** 211 * Creates an {@link ArrayList} copy from a collection. 212 * 213 * @param <E> The element type. 214 * @param value The collection to copy from. 215 * @return A new modifiable list. 216 */ 217 public static <E> ArrayList<E> listFrom(Collection<E> value) { 218 return listFrom(value, false); 219 } 220 221 /** 222 * Creates an {@link ArrayList} copy from a collection. 223 * 224 * @param <K> The key type. 225 * @param <V> The value type. 226 * @param value The collection to copy from. 227 * @return A new modifiable list. 228 */ 229 public static <K,V> LinkedHashMap<K,V> mapFrom(Map<K,V> value) { 230 if (value == null) 231 return null; 232 return new LinkedHashMap<>(value); 233 } 234 235 /** 236 * Creates an {@link ArrayList} copy from a collection. 237 * 238 * @param <E> The element type. 239 * @param value The collection to copy from. 240 * @param nullIfEmpty If <jk>true</jk> will return <jk>null</jk> if the collection is empty. 241 * @return A new modifiable list. 242 */ 243 public static <E> ArrayList<E> listFrom(Collection<E> value, boolean nullIfEmpty) { 244 if (value == null || (nullIfEmpty && value.isEmpty())) 245 return null; 246 ArrayList<E> l = new ArrayList<>(); 247 value.forEach(x -> l.add(x)); 248 return l; 249 } 250 251 /** 252 * Convenience method for creating a {@link LinkedHashSet}. 253 * 254 * @param <E> The element type. 255 * @param values The values to initialize the set with. 256 * @return A new modifiable set. 257 */ 258 @SafeVarargs 259 public static <E> LinkedHashSet<E> set(E...values) { 260 LinkedHashSet<E> l = new LinkedHashSet<>(); 261 for (E v : values) 262 l.add(v); 263 return l; 264 } 265 266 /** 267 * Convenience method for creating an unmodifiable {@link LinkedHashSet}. 268 * 269 * @param <E> The element type. 270 * @param values The values to initialize the set with. 271 * @return A new unmodifiable set. 272 */ 273 @SafeVarargs 274 public static <E> Set<E> uset(E...values) { 275 return unmodifiable(set(values)); 276 } 277 278 /** 279 * Convenience method for creating an unmodifiable list. 280 * 281 * @param <E> The element type. 282 * @param values The values to initialize the list with. 283 * @return A new unmodifiable list, or <jk>null</jk> if the array was <jk>null</jk>. 284 */ 285 @SafeVarargs 286 public static <E> List<E> ulist(E...values) { 287 if (values == null) 288 return null; 289 return unmodifiable(alist(values)); 290 } 291 292 /** 293 * Convenience method for creating a {@link TreeSet}. 294 * 295 * @param <E> The element type. 296 * @param values The values to initialize the set with. 297 * @return A new modifiable set. 298 */ 299 @SafeVarargs 300 public static <E> TreeSet<E> sortedSet(E...values) { 301 TreeSet<E> l = new TreeSet<>(); 302 for (E v : values) 303 l.add(v); 304 return l; 305 } 306 307 /** 308 * Creates a new {@link TreeSet} from the specified collection. 309 * 310 * @param <E> The element type. 311 * @param value The value to copy from. 312 * @return A new {@link TreeSet}, or <jk>null</jk> if the input was null. 313 */ 314 public static <E> TreeSet<E> sortedSetFrom(Collection<E> value) { 315 if (value == null) 316 return null; 317 TreeSet<E> l = new TreeSet<>(); 318 value.forEach(x -> l.add(x)); 319 return l; 320 } 321 322 /** 323 * Creates a new {@link TreeSet} from the specified collection. 324 * 325 * @param <E> The element type. 326 * @param value The value to copy from. 327 * @param nullIfEmpty If <jk>true</jk> returns <jk>null</jk> if the collection is empty. 328 * @return A new {@link TreeSet}, or <jk>null</jk> if the input was null. 329 */ 330 public static <E> TreeSet<E> sortedSetFrom(Collection<E> value, boolean nullIfEmpty) { 331 if (value == null || (nullIfEmpty && value.isEmpty())) 332 return null; 333 TreeSet<E> l = new TreeSet<>(); 334 value.forEach(x -> l.add(x)); 335 return l; 336 } 337 338 /** 339 * Convenience method for creating a {@link LinkedHashMap}. 340 * 341 * @param <K> The key type. 342 * @param <V> The value type. 343 * @return A new modifiable map. 344 */ 345 public static <K,V> LinkedHashMap<K,V> map() { 346 LinkedHashMap<K,V> m = new LinkedHashMap<>(); 347 return m; 348 } 349 350 /** 351 * Convenience method for creating a {@link LinkedHashMap}. 352 * 353 * @param <K> The key type. 354 * @param <V> The value type. 355 * @param k1 Key 1. 356 * @param v1 Value 1. 357 * @return A new modifiable map. 358 */ 359 public static <K,V> LinkedHashMap<K,V> map(K k1, V v1) { 360 LinkedHashMap<K,V> m = new LinkedHashMap<>(); 361 m.put(k1, v1); 362 return m; 363 } 364 365 /** 366 * Convenience method for creating a {@link LinkedHashMap}. 367 * 368 * @param <K> The key type. 369 * @param <V> The value type. 370 * @param k1 Key 1. 371 * @param v1 Value 1. 372 * @param k2 Key 2. 373 * @param v2 Value 2. 374 * @return A new modifiable map. 375 */ 376 public static <K,V> LinkedHashMap<K,V> map(K k1, V v1, K k2, V v2) { 377 LinkedHashMap<K,V> m = new LinkedHashMap<>(); 378 m.put(k1, v1); 379 m.put(k2, v2); 380 return m; 381 } 382 383 /** 384 * Convenience method for creating a {@link LinkedHashMap}. 385 * 386 * @param <K> The key type. 387 * @param <V> The value type. 388 * @param k1 Key 1. 389 * @param v1 Value 1. 390 * @param k2 Key 2. 391 * @param v2 Value 2. 392 * @param k3 Key 3. 393 * @param v3 Value 3. 394 * @return A new modifiable map. 395 */ 396 public static <K,V> LinkedHashMap<K,V> map(K k1, V v1, K k2, V v2, K k3, V v3) { 397 LinkedHashMap<K,V> m = new LinkedHashMap<>(); 398 m.put(k1, v1); 399 m.put(k2, v2); 400 m.put(k3, v3); 401 return m; 402 } 403 404 /** 405 * Convenience method for creating a {@link TreeMap}. 406 * 407 * @param <K> The key type. 408 * @param <V> The value type. 409 * @return A new modifiable set. 410 */ 411 public static <K,V> TreeMap<K,V> sortedMap() { 412 return new TreeMap<>(); 413 } 414 415 /** 416 * Convenience method for copying a list. 417 * 418 * @param <E> The element type. 419 * @param value The list to copy. 420 * @return A new modifiable list. 421 */ 422 public static <E> ArrayList<E> copyOf(List<E> value) { 423 return value == null ? null : new ArrayList<>(value); 424 } 425 426 /** 427 * Convenience method for creating an {@link ArrayList} and sorting it. 428 * 429 * @param <E> The element type. 430 * @param values The values to initialize the list with. 431 * @return A new modifiable list. 432 */ 433 @SuppressWarnings({ "rawtypes", "unchecked" }) 434 @SafeVarargs 435 public static <E> ArrayList<E> sortedList(E...values) { 436 ArrayList<E> l = list(values); 437 Collections.sort((List<Comparable>) l); 438 return l; 439 } 440 441 /** 442 * Convenience method for creating an {@link ArrayList} and sorting it. 443 * 444 * @param <E> The element type. 445 * @param comparator The comparator to use to sort the list. 446 * @param values The values to initialize the list with. 447 * @return A new modifiable list. 448 */ 449 public static <E> ArrayList<E> sortedList(Comparator<E> comparator, E[] values) { 450 ArrayList<E> l = list(values); 451 Collections.sort(l, comparator); 452 return l; 453 } 454 455 /** 456 * Convenience method for creating an {@link ArrayList} and sorting it. 457 * 458 * @param <E> The element type. 459 * @param comparator The comparator to use to sort the list. 460 * @param value The values to initialize the list with. 461 * @return A new modifiable list. 462 */ 463 public static <E> ArrayList<E> sortedList(Comparator<E> comparator, Collection<E> value) { 464 ArrayList<E> l = listFrom(value); 465 Collections.sort(l, comparator); 466 return l; 467 } 468 469 /** 470 * Wraps the specified list in {@link Collections#unmodifiableList(List)}. 471 * 472 * @param <E> The element type. 473 * @param value The list to wrap. 474 * @return The wrapped list. 475 */ 476 public static <E> List<E> unmodifiable(List<E> value) { 477 return value == null ? null: Collections.unmodifiableList(value); 478 } 479 480 /** 481 * Wraps the specified set in {@link Collections#unmodifiableSet(Set)}. 482 * 483 * @param <E> The element type. 484 * @param value The set to wrap. 485 * @return The wrapped set. 486 */ 487 public static <E> Set<E> unmodifiable(Set<E> value) { 488 return value == null ? null: Collections.unmodifiableSet(value); 489 } 490 491 /** 492 * Wraps the specified map in {@link Collections#unmodifiableMap(Map)}. 493 * 494 * @param <K> The key type. 495 * @param <V> The value type. 496 * @param value The map to wrap. 497 * @return The wrapped map. 498 */ 499 public static <K,V> Map<K,V> unmodifiable(Map<K,V> value) { 500 return value == null ? null: Collections.unmodifiableMap(value); 501 } 502 503 /** 504 * Wraps the specified list in {@link Collections#unmodifiableList(List)}. 505 * 506 * @param <E> The element type. 507 * @param value The list to wrap. 508 * @return The wrapped list. 509 */ 510 public static <E> List<E> synced(List<E> value) { 511 return value == null ? null: Collections.synchronizedList(value); 512 } 513 514 /** 515 * Wraps the specified set in {@link Collections#unmodifiableSet(Set)}. 516 * 517 * @param <E> The element type. 518 * @param value The set to wrap. 519 * @return The wrapped set. 520 */ 521 public static <E> Set<E> synced(Set<E> value) { 522 return value == null ? null: Collections.synchronizedSet(value); 523 } 524 525 /** 526 * Wraps the specified map in {@link Collections#unmodifiableMap(Map)}. 527 * 528 * @param <K> The key type. 529 * @param <V> The value type. 530 * @param value The map to wrap. 531 * @return The wrapped map. 532 */ 533 public static <K,V> Map<K,V> synced(Map<K,V> value) { 534 return value == null ? null: Collections.synchronizedMap(value); 535 } 536 537 /** 538 * Converts the specified collection to an array. 539 * 540 * @param <E> The element type. 541 * @param value The collection to convert. 542 * @param componentType The component type of the array. 543 * @return A new array. 544 */ 545 @SuppressWarnings("unchecked") 546 public static <E> E[] array(Collection<E> value, Class<E> componentType) { 547 if (value == null) 548 return null; 549 E[] array = (E[])Array.newInstance(componentType, value.size()); 550 return value.toArray(array); 551 } 552 553 /** 554 * Iterates the specified list in reverse order. 555 * 556 * @param <E> The element type. 557 * @param value The list to iterate. 558 * @param action The action to perform. 559 */ 560 public static <E> void forEachReverse(List<E> value, Consumer<E> action) { 561 if (value instanceof ArrayList) { 562 for (int i = value.size()-1; i >= 0; i--) 563 action.accept(value.get(i)); 564 } else { 565 ListIterator<E> i = value.listIterator(value.size()); 566 while (i.hasPrevious()) 567 action.accept(i.previous()); 568 } 569 } 570 571 /** 572 * Iterates the specified array in reverse order. 573 * 574 * @param <E> The element type. 575 * @param value The array to iterate. 576 * @param action The action to perform. 577 */ 578 public static <E> void forEachReverse(E[] value, Consumer<E> action) { 579 for (int i = value.length-1; i >= 0; i--) 580 action.accept(value[i]); 581 } 582 583 /** 584 * Adds all the specified values to the specified collection. 585 * Creates a new set if the value is <jk>null</jk>. 586 * 587 * @param <E> The element type. 588 * @param value The collection to add to. 589 * @param entries The entries to add. 590 * @return The set. 591 */ 592 @SafeVarargs 593 public static <E> Set<E> addAll(Set<E> value, E...entries) { 594 if (entries != null) { 595 if (value == null) 596 value = set(entries); 597 else 598 Collections.addAll(value, entries); 599 } 600 return value; 601 } 602 603 /** 604 * Adds all the specified values to the specified collection. 605 * Creates a new set if the value is <jk>null</jk>. 606 * 607 * @param <E> The element type. 608 * @param value The collection to add to. 609 * @param entries The entries to add. 610 * @return The set. 611 */ 612 @SafeVarargs 613 public static <E> SortedSet<E> addAll(SortedSet<E> value, E...entries) { 614 if (entries != null) { 615 if (value == null) 616 value = sortedSet(entries); 617 else 618 Collections.addAll(value, entries); 619 } 620 return value; 621 } 622 623 /** 624 * Adds all the specified values to the specified collection. 625 * Creates a new set if the value is <jk>null</jk>. 626 * 627 * @param <E> The element type. 628 * @param value The collection to add to. 629 * @param entries The entries to add. 630 * @return The set. 631 */ 632 @SafeVarargs 633 public static <E> List<E> addAll(List<E> value, E...entries) { 634 if (entries != null) { 635 if (value == null) 636 value = list(entries); 637 else 638 Collections.addAll(value, entries); 639 } 640 return value; 641 } 642 643 /** 644 * Adds all the specified values to the specified collection. 645 * Creates a new set if the value is <jk>null</jk>. 646 * 647 * @param <E> The element type. 648 * @param value The collection to add to. 649 * @param entries The entries to add. 650 * @return The set. 651 */ 652 @SafeVarargs 653 public static <E> List<E> prependAll(List<E> value, E...entries) { 654 if (entries != null) { 655 if (value == null) 656 value = list(entries); 657 else 658 value.addAll(0, alist(entries)); 659 } 660 return value; 661 } 662 663 /** 664 * Returns the last entry in a list. 665 * 666 * @param <E> The element type. 667 * @param l The list. 668 * @return The last element, or <jk>null</jk> if the list is <jk>null</jk> or empty. 669 */ 670 public static <E> E last(List<E> l) { 671 if (l == null || l.isEmpty()) 672 return null; 673 return l.get(l.size()-1); 674 } 675 676 /** 677 * Returns the last entry in an array. 678 * 679 * @param <E> The element type. 680 * @param l The array. 681 * @return The last element, or <jk>null</jk> if the array is <jk>null</jk> or empty. 682 */ 683 public static <E> E last(E[] l) { 684 if (l == null || l.length == 0) 685 return null; 686 return l[l.length-1]; 687 } 688 689 /** 690 * Returns an optional of the specified value. 691 * 692 * @param <T> The component type. 693 * @param value The value. 694 * @return A new Optional. 695 */ 696 public static <T> Optional<T> optional(T value) { 697 return Optional.ofNullable(value); 698 } 699 700 /** 701 * Returns an empty {@link Optional}. 702 * 703 * @param <T> The component type. 704 * @return An empty {@link Optional}. 705 */ 706 public static <T> Optional<T> empty() { 707 return Optional.empty(); 708 } 709 710 /** 711 * Returns <jk>true</jk> if the specified collection is not <jk>null</jk> and not empty. 712 * 713 * @param <E> The element type. 714 * @param value The value being checked. 715 * @return <jk>true</jk> if the specified collection is not <jk>null</jk> and not empty. 716 */ 717 public static <E> boolean isNotEmpty(Collection<E> value) { 718 return value != null && ! value.isEmpty(); 719 } 720 721 /** 722 * Returns <jk>true</jk> if the specified map is not <jk>null</jk> and not empty. 723 * 724 * @param <K> The key type. 725 * @param <V> The value type. 726 * @param value The value being checked. 727 * @return <jk>true</jk> if the specified map is not <jk>null</jk> and not empty. 728 */ 729 public static <K,V> boolean isNotEmpty(Map<K,V> value) { 730 return value != null && ! value.isEmpty(); 731 } 732}