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