org.cp.elements.util.CollectionUtils Maven / Gradle / Ivy
/*
* Copyright 2011-Present Author or Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.cp.elements.util;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.cp.elements.lang.Assert;
import org.cp.elements.lang.FilteringTransformer;
import org.cp.elements.lang.Renderer;
import org.cp.elements.lang.StringUtils;
import org.cp.elements.lang.Transformer;
import org.cp.elements.lang.annotation.NotNull;
import org.cp.elements.lang.annotation.NullSafe;
import org.cp.elements.lang.annotation.Nullable;
import org.cp.elements.lang.support.ToStringRenderer;
/**
* An abstract utility {@link Class} providing methods and functionality for working with the Java Collections Framework
* and specifically the {@link Collection} classes.
*
* @author John J. Blum
* @see java.lang.Iterable
* @see java.util.Collection
* @see java.util.Collections
* @see java.util.Enumeration
* @see java.util.Iterator
* @see java.util.List
* @see java.util.Set
* @see java.util.stream.Collectors
* @see org.cp.elements.lang.FilteringTransformer
* @see org.cp.elements.lang.Renderer
* @see org.cp.elements.lang.Transformer
* @see org.cp.elements.lang.support.ToStringRenderer
* @since 1.0.0
*/
@SuppressWarnings("unused")
public abstract class CollectionUtils {
private static final Random random = new Random();
/**
* Adds all elements from the given array to the given {@link Collection}.
*
* @param {@link Class} type of the elements in the array and {@link Collection}.
* @param {@link Class} type of the target {@link Collection}.
* @param collection {@link Collection} in which to add the elements from the array; must not be {@literal null}.
* @param array array containing the elements to add to the target {@link Collection}.
* @return the given {@link Collection}.
* @throws IllegalArgumentException if the {@link Collection} is {@literal null}.
* @see #addAll(Collection, Iterable)
* @see java.util.Collection
*/
@SuppressWarnings("unchecked")
public static @NotNull > T addAll(@NotNull T collection, E... array) {
Assert.notNull(collection, "Collection is required");
Collections.addAll(collection, ArrayUtils.nullSafeArray(array));
return collection;
}
/**
* Adds all elements from the given {@link Iterable} to the given {@link Collection}.
*
* @param {@link Class} type of the elements in the {@link Collection} and {@link Iterable}.
* @param {@link Class} type of the target {@link Collection}.
* @param collection {@link Collection} in which to add the elements from the {@link Iterable};
* must not be {@literal null}.
* @param iterable {@link Iterable} containing the elements to add to the target {@link Collection}.
* @return the given {@link Collection}.
* @throws IllegalArgumentException if {@link Collection} is {@literal null}.
* @see java.util.Collection
* @see java.lang.Iterable
*/
public static @NotNull > T addAll(@NotNull T collection, Iterable iterable) {
Assert.notNull(collection, "Collection is required");
for (E element : nullSafeIterable(iterable)) {
collection.add(element);
}
return collection;
}
/**
* Adapts the {@link Iterator} into an instance of the {@link Enumeration} interface.
* Returns an empty {@link Enumeration} if the {@link Iterator} is null.
*
* @param Class type of the elements in the {@link Iterator}.
* @param iterator {@link Iterator} to adapt into an {@link Enumeration}.
* @return an {@link Enumeration} implementation enumerating over the elements in the {@link Iterator}.
* @see java.util.Collections#emptyEnumeration()
* @see #asIterator(java.util.Enumeration)
* @see java.util.Enumeration
* @see java.util.Iterator
*/
@NullSafe
public static @NotNull Enumeration asEnumeration(@Nullable Iterator iterator) {
return iterator == null ? Collections.emptyEnumeration() : new Enumeration<>() {
@Override
public boolean hasMoreElements() {
return iterator.hasNext();
}
@Override
public T nextElement() {
return iterator.next();
}
};
}
/**
* Adapts the {@link Enumeration} into an instance of the {@link Iterable} interface.
*
* @param Class type of the elements in the {@link Enumeration}.
* @param enumeration {@link Enumeration} to adapt into an {@link Iterable}.
* @return an {@link Iterable} implementation backed by the {@link Enumeration}.
* @see #asIterator(java.util.Enumeration)
* @see java.util.Enumeration
* @see java.lang.Iterable
*/
@NullSafe
public static @NotNull Iterable asIterable(@Nullable Enumeration enumeration) {
return () -> asIterator(enumeration);
}
/**
* Adapts the {@link Iterator} into an instance of the {@link Iterable} interface.
*
* @param Class type of the elements in the {@link Iterator}.
* @param iterator {@link Iterator} to adapt into an {@link Iterable}.
* @return an {@link Iterable} implementation backed by the {@link Iterator}.
* @see #nullSafeIterator(Iterator)
* @see java.util.Iterator
* @see java.lang.Iterable
*/
@NullSafe
public static @NotNull Iterable asIterable(@Nullable Iterator iterator) {
return () -> nullSafeIterator(iterator);
}
/**
* Adapts the {@link Enumeration} into an instance of the {@link Iterator} interface.
*
* @param Class type of the elements in the {@link Enumeration}.
* @param enumeration {@link Enumeration} to adapt into an {@link Iterator}.
* @return an {@link Iterator} implementation iterating over the elements in the {@link Enumeration}.
* @see java.util.Collections#emptyIterator()
* @see #asEnumeration(java.util.Iterator)
* @see java.util.Enumeration
* @see java.util.Iterator
*/
@NullSafe
public static @NotNull Iterator asIterator(@Nullable Enumeration enumeration) {
return enumeration == null ? Collections.emptyIterator() : new Iterator<>() {
@Override
public boolean hasNext() {
return enumeration.hasMoreElements();
}
@Override
public T next() {
return enumeration.nextElement();
}
};
}
/**
* Converts the given {@link Object array} into a mutable {@link List}.
*
* @param {@link Class type} of the array elements.
* @param array array to convert into a {@link List}.
* @return a mutable {@link List} containing the array elements.
* @see org.cp.elements.util.ArrayUtils#nullSafeArray(Object[])
* @see java.util.List
*/
@NullSafe
@SafeVarargs
public static @NotNull List asList(T... array) {
return new ArrayList<>(Arrays.asList(ArrayUtils.nullSafeArray(array)));
}
/**
* Null-safe method to convert the given {@link Iterable} collection of elements into a {@link List}.
*
* @param {@link Class} type of the elements in the {@link Iterable}.
* @param iterable {@link Iterable} to convert into a {@link List}.
* @return a {@link List} of the elements from the {@link Iterable} object.
* @see #nullSafeIterable(Iterable)
* @see java.lang.Iterable
* @see java.util.List
*/
@NullSafe
public static @NotNull List asList(@Nullable Iterable iterable) {
return iterable instanceof Collection
? new ArrayList<>((Collection) iterable)
: StreamSupport.stream(nullSafeIterable(iterable).spliterator(), false)
.collect(Collectors.toList());
}
/**
* Null-safe method to convert the array of elements into a {@link Set}.
*
* @param {@link Class} type of the elements in the array.
* @param elements array of elements to convert into a {@link Set}.
* @return a {@link Set} from the given array of elements.
* @see java.util.Set
*/
@NullSafe
@SafeVarargs
public static @NotNull Set asSet(T... elements) {
return Arrays.stream(ArrayUtils.nullSafeArray(elements)).collect(Collectors.toSet());
}
/**
* Null-safe method to convert the given {@link Iterable} collection of elements into a {@link Set}.
*
* @param {@link Class} type of the elements in the {@link Iterable}.
* @param iterable {@link Iterable} to convert into a {@link Set}.
* @return a {@link Set} of the elements from the {@link Iterable} object.
* @see #nullSafeIterable(Iterable)
* @see java.lang.Iterable
* @see java.util.Set
*/
@NullSafe
public static @NotNull Set asSet(@Nullable Iterable iterable) {
return iterable instanceof Collection
? new HashSet<>((Collection) iterable)
: StreamSupport.stream(nullSafeIterable(iterable).spliterator(), false)
.collect(Collectors.toSet());
}
/**
* Null-safe method to determine if any of the elements in the array are contained in the given {@link Collection}.
*
* @param collection {@link Collection} to evaluate for containment of the array elements.
* @param elements array of elements to evaluate for containment in the {@link Collection}.
* @return a boolean value indicating whether any (at least 1) elements from the array are contained
* in the given {@link Collection}.
* @see java.util.Collection#contains(Object)
*/
@NullSafe
public static boolean containsAny(@Nullable Collection> collection, Object... elements) {
if (Objects.nonNull(collection)) {
for (Object element : ArrayUtils.nullSafeArray(elements)) {
if (collection.contains(element)) {
return true;
}
}
}
return false;
}
/**
* Counts the number of elements in the {@link Iterable} collection.
*
* If {@link Iterable} is {@literal null} or contains no elements, then count will be {@literal 0}.
* If the {@link Iterable} is a {@link Collection}, then {@link Collection#size()} is returned,
* otherwise the elements of the {@link Iterable} are iterated over, counting the number of elements
* in the iteration to determine it's size.
*
* @param iterable {@link Iterable} collection of elements being evaluated.
* @return an integer value indicating the number of elements in the {@link Iterable} collection (i.e. size).
* @see #count(Iterable, Predicate)
* @see java.util.Collection#size()
* @see java.lang.Iterable
*/
@NullSafe
public static long count(@Nullable Iterable> iterable) {
return iterable instanceof Collection
? ((Collection>) iterable).size()
: count(iterable, element -> true);
}
/**
* Counts the number of elements in the {@link Iterable} collection accepted by the {@link Predicate}.
*
* @param {@link Class} type of the elements in the {@link Iterable} collection.
* @param iterable {@link Iterable} collection of elements being evaluated.
* @param predicate {@link Predicate} used to determine the number of elements (count)
* in the {@link Iterable} collection accepted by the {@link Predicate}.
* @return an integer value indicating the number of elements in the {@link Iterable} collection
* accepted by the {@link Predicate}.
* @throws IllegalArgumentException if {@link Predicate} is {@literal null}.
* @see java.util.function.Predicate
* @see #nullSafeIterable(Iterable)
* @see java.lang.Iterable
*/
public static long count(@Nullable Iterable iterable, @NotNull Predicate predicate) {
Assert.notNull(predicate, "Predicate is required");
return StreamSupport.stream(nullSafeIterable(iterable).spliterator(), false)
.filter(predicate)
.count();
}
/**
* Returns the given {@link Iterable} if not {@literal null} or empty, otherwise returns the {@code defaultIterable}.
*
* @param {@link Class} type of the elements in the {@link Iterable Iterables}.
* @param {@link Class} type of the {@link Iterable}.
* @param iterable {@link Iterable} to evaluate.
* @param defaultIterable {@link Iterable} to return if the given {@code iterable} is {@literal null} or empty.
* @return {@code iterable} if not {@literal null} or empty otherwise return {@code defaultIterable}.
* @see java.lang.Iterable
*/
public static @Nullable > T defaultIfEmpty(@Nullable T iterable,
@Nullable T defaultIterable) {
return iterable != null && iterable.iterator().hasNext() ? iterable : defaultIterable;
}
/**
* Returns an empty {@link Iterable} with no elements.
*
* @param Class type of the elements in the {@link Iterable}.
* @return an empty {@link Iterable}.
* @see java.util.Collections#emptyIterator()
* @see java.lang.Iterable
*/
@NullSafe
public static @NotNull Iterable emptyIterable() {
return Collections::emptyIterator;
}
/**
* Returns a filtered {@link Collection} containing only the elements from the given {@link Collection} accepted by
* the {@link Predicate}.
*
* @param {@link Class type} of the elements in the {@link Collection}.
* @param collection {@link Collection} to filter.
* @param predicate {@link Predicate} used to filter the {@link Collection}.
* @return a filtered {@link Collection} of elements accepted by the {@link Predicate}.
* @throws IllegalArgumentException if either the {@link Collection} or {@link Predicate} are {@literal null}.
* @see java.util.function.Predicate
* @see java.util.Collection
*/
public static @NotNull Collection filter(@NotNull Collection collection, @NotNull Predicate predicate) {
Assert.notNull(collection, "Collection is required");
Assert.notNull(predicate, "Predicate is required");
return collection.stream()
.filter(predicate)
.collect(Collectors.toList());
}
/**
* Filters and transforms the {@link Collection} of elements using the specified {@link FilteringTransformer}.
*
* @param Class type of the elements in the {@link Collection}.
* @param collection {@link Collection} to filter and transform.
* @param filteringTransformer {@link FilteringTransformer} used to filter and transform the {@link Collection}.
* @return a filtered, transformed {@link Collection} of elements accepted and modified
* by the {@link FilteringTransformer}.
* @throws IllegalArgumentException if either the {@link Collection} or {@link FilteringTransformer} are null.
* @see org.cp.elements.lang.FilteringTransformer
* @see java.util.Collection
*/
public static @NotNull Collection filterAndTransform(@NotNull Collection collection,
@NotNull FilteringTransformer filteringTransformer) {
Assert.notNull(collection, "Collection is required");
Assert.notNull(filteringTransformer, "FilteringTransformer is required");
return collection.stream()
.filter(filteringTransformer::accept)
.map(filteringTransformer::transform)
.collect(Collectors.toList());
}
/**
* Searches the {@link Iterable} for all elements accepted by the {@link Predicate}.
*
* @param {@link Class type} of the elements in the {@link Iterable}.
* @param iterable {@link Iterable} collection of elements to search.
* @param predicate {@link Predicate} used to find elements from the {@link Iterable} collection
* accepted by the {@link Predicate}.
* @return a {@link List} containing elements from the {@link Iterable} collection
* accepted by the {@link Predicate}.
* @throws IllegalArgumentException if {@link Predicate} is {@literal null}.
* @see java.util.function.Predicate
* @see #findOne(Iterable, Predicate)
* @see #nullSafeIterable(Iterable)
* @see java.lang.Iterable
*/
public static @NotNull List findAll(@Nullable Iterable iterable, @NotNull Predicate predicate) {
Assert.notNull(predicate, "Predicate is required");
return StreamSupport.stream(nullSafeIterable(iterable).spliterator(), false)
.filter(predicate)
.collect(Collectors.toList());
}
/**
* Searches the {@link Iterable} for the first element accepted by the {@link Predicate}.
*
* @param {@link Class} type of the elements in the {@link Iterable}.
* @param iterable {@link Iterable} collection of elements to search.
* @param predicate {@link Predicate} used to find the first element from the {@link Iterable}
* accepted by the {@link Predicate}.
* @return the first element from the {@link Iterable} accepted by the {@link Predicate},
* or {@literal null} if no such element is found.
* @throws IllegalArgumentException if {@link Predicate} is {@literal null}.
* @see java.util.function.Predicate
* @see #findAll(Iterable, Predicate)
* @see #nullSafeIterable(Iterable)
* @see java.lang.Iterable
*/
public static @Nullable T findOne(@Nullable Iterable iterable, @NotNull Predicate predicate) {
Assert.notNull(predicate, "Predicate is required");
return StreamSupport.stream(nullSafeIterable(iterable).spliterator(), false)
.filter(predicate)
.findFirst()
.orElse(null);
}
/**
* Gets the last element in the given {@link List}.
*
* @param {@link Class type} of elements in the given {@link List}.
* @param list {@link List} from which to return the last element.
* @return the last element in the given {@link List}
* or {@literal null} if the given {@link List} is {@literal null}.
* @see #getLastElement(List, Object)
* @see java.util.List
*/
public static @Nullable T getLastElement(@Nullable List list) {
return getLastElement(list, null);
}
/**
* Gets the last element in the given {@link List} or returns the given {@link Object default value}
* if the {@link List} is {@literal null} or {@literal empty}.
*
* @param {@link Class type} of elements in the given {@link List}.
* @param list {@link List} from which to return the last element.
* @param defaultValue {@link Object} to return if the {@link List} is {@literal null} or {@link List#isEmpty()}.
* @return the last element in the given {@link List} or {@link T default value}
* if the given {@link List} is {@literal null} or {@literal empty}.
* @see #isNotEmpty(Iterable)
* @see java.util.List
*/
public static @Nullable T getLastElement(@Nullable List list, @Nullable T defaultValue) {
return isNotEmpty(list) ? list.get(list.size() - 1) : defaultValue;
}
/**
* Determines whether the {@link Iterable} is empty.
*
* The {@link Iterable} is empty if it contains no elements
* or the {@link Iterable} object reference is {@literal null}.
*
* @param iterable {@link Iterable} to evaluate.
* @return a boolean value indicating whether the {@link Iterable} is empty.
* @see #isNotEmpty(Iterable)
* @see java.lang.Iterable
*/
@NullSafe
public static boolean isEmpty(@Nullable Iterable> iterable) {
return iterable == null || !iterable.iterator().hasNext();
}
/**
* Determines whether the {@link Iterable} is not empty.
*
* The {@link Iterable} is not empty iff it is not {@literal null} and contains at least 1 element.
*
* @param iterable {@link Iterable} to evaluate.
* @return a boolean value indicating whether the {@link Iterable} is not empty.
* @see #isEmpty(Iterable)
* @see java.lang.Iterable
*/
@NullSafe
public static boolean isNotEmpty(@Nullable Iterable> iterable) {
return !isEmpty(iterable);
}
/**
* Determines whether the give {@link Collection} has the given {@link Integer#TYPE size}.
*
* @param collection {@link Collection} to evaluate.
* @param size {@link Integer} specifying the expected size of the {@link Collection}.
* @return a boolean value indicating whether the given {@link Collection} has the given {@link Integer#TYPE size}.
* @see #nullSafeSize(Collection)
* @see #isSizeOne(Collection)
* @see java.util.Collection
*/
public static boolean isSize(@Nullable Collection> collection, int size) {
return nullSafeSize(collection) == size;
}
/**
* Null-safe operation to determine whether the size of the given {@link Collection} is 1.
*
* @param collection {@link Collection} to evaluate.
* @return a boolean indicating whether the size of the given {@link Collection} is 1.
* @see #nullSafeSize(Collection)
* @see #isSize(Collection, int)
* @see java.util.Collection
*/
@NullSafe
public static boolean isSizeOne(@Nullable Collection> collection) {
return isSize(collection, 1);
}
/**
* Determines whether the given {@link Collection} is not {@literal null} and contains no {@literal null} elements.
*
* @param collection {@link Collection} to evaluate.
* @return a boolean value indicating whether the given {@link Collection} is not {@literal null}
* and contains no {@literal null} elements.
* @see java.util.Collection
*/
@NullSafe
public static boolean noNullElements(@Nullable Collection> collection) {
return collection != null && collection.stream()
.filter(Objects::nonNull)
.count() == collection.size();
}
/**
* Null-safe method returning the given {@link Collection} if not {@literal null} or an empty {@link Collection}
* if {@literal null}.
*
* @param {@link Class} type of the elements in the {@link Collection}.
* @param collection {@link Collection} to evaluate.
* @return the given {@link Collection} if not {@literal null} or an empty {@link Collection} if {@literal null}.
* @see java.util.Collection
*/
@NullSafe
public static @NotNull Collection nullSafeCollection(@Nullable Collection collection) {
return collection != null ? collection : Collections.emptyList();
}
/**
* Null-safe method returning the given {@link Enumeration} or an empty {@link Enumeration} if null.
*
* @param Class type of the elements in the {@link Enumeration}.
* @param enumeration {@link Enumeration} to evaluate.
* @return the given {@link Enumeration} or an empty {@link Enumeration} if null.
* @see java.util.Collections#emptyEnumeration()
* @see java.util.Enumeration
*/
@NullSafe
public static @NotNull Enumeration nullSafeEnumeration(@Nullable Enumeration enumeration) {
return enumeration != null ? enumeration : Collections.emptyEnumeration();
}
/**
* Null-safe method returning the given {@link Iterable} or an empty {@link Iterable} if null.
*
* @param Class type of the elements in the {@link Iterable}.
* @param iterable {@link Iterable} to evaluate.
* @return the given {@link Iterable} or an empty {@link Iterable} if null.
* @see #emptyIterable()
* @see java.lang.Iterable
*/
@NullSafe
public static @NotNull Iterable nullSafeIterable(@Nullable Iterable iterable) {
return iterable != null ? iterable : emptyIterable();
}
/**
* Null-safe method returning the given {@link Iterator} or an empty {@link Iterator} if null.
*
* @param Class type of the elements in the {@link Iterator}.
* @param iterator {@link Iterator} to evaluate.
* @return the given {@link Iterator} or an empty {@link Iterator} if null.
* @see java.util.Collections#emptyIterator()
* @see java.util.Iterator
*/
@NullSafe
public static @NotNull Iterator nullSafeIterator(@Nullable Iterator iterator) {
return iterator != null ? iterator : Collections.emptyIterator();
}
/**
* Null-safe method returning the given {@link List} or an empty {@link List} if null.
*
* @param Class type of the elements in the {@link List}.
* @param list {@link List} to evaluate.
* @return the given {@link List} or an empty {@link List} if null.
* @see java.util.Collections#emptyList()
* @see java.util.List
*/
@NullSafe
public static @NotNull List nullSafeList(@Nullable List list) {
return list != null ? list : Collections.emptyList();
}
/**
* Null-safe method returning the given {@link Set} or an empty {@link Set} if null.
*
* @param Class type of the elements in the {@link Set}.
* @param set {@link Set} to evaluate.
* @return the given {@link Set} or an empty {@link Set} if null.
* @see java.util.Collections#emptySet()
* @see java.util.Set
*/
@NullSafe
public static @NotNull Set nullSafeSet(@Nullable Set set) {
return set != null ? set : Collections.emptySet();
}
/**
* Determines the size of the {@link Collection}.
*
* @param collection {@link Collection} to evaluate.
* @return the size of, or number of elements in the {@link Collection},
* return {@literal 0} if the {@link Collection} is {@literal null}.
* @see java.util.Collection#size()
*/
@NullSafe
public static int nullSafeSize(@Nullable Collection> collection) {
return collection != null ? collection.size() : 0;
}
/**
* Shuffles the elements in the {@link List}. This method guarantees a random, uniform shuffling of the elements
* in the {@link List} with an operational efficiency of O(n).
*
* @param Class type of the elements in the {@link List}.
* @param list {@link List} of elements to shuffle.
* @return the {@link List} of elements shuffled.
* @see java.util.Collections#swap(List, int, int)
* @see #isNotEmpty(Iterable)
* @see java.util.List
*/
public static @Nullable List shuffle(@Nullable List list) {
if (isNotEmpty(list)) {
random.setSeed(System.currentTimeMillis());
for (int index = 0, sizeMinusOne = nullSafeSize(list) - 1; index < sizeMinusOne; index++) {
int randomIndex = random.nextInt(sizeMinusOne - index) + 1;
Collections.swap(list, index, index + randomIndex);
}
}
return list;
}
/**
* Creates a sub-list from the given {@link List} with values at the specified indices.
*
* @param Class type of the elements in the {@link List}.
* @param list {@link List} of elements from which to create the sub-list.
* @param indices array of indices referring to values in the {@link List} to include in the sub-list.
* @return a sub-list containing values at the given indices in the {@link List}.
* @throws IllegalArgumentException if either the {@link List} or array of indices are null.
* @throws IndexOutOfBoundsException if the indices are not valid indexes in the {@link List}.
* @see java.util.List
*/
public static @NotNull List subList(@NotNull List list, int... indices) {
Assert.notNull(list, "List is required");
Assert.notNull(indices, "Indices are required");
List subList = new ArrayList<>(indices.length);
for (int index : indices) {
subList.add(list.get(index));
}
return subList;
}
/**
* Null-safe utility method returning an array from the given {@link Collection}.
*
* @param {@link Class} type of the elements in the {@link Collection}.
* @param collection {@link Collection} to convert into an array.
* @param componentType {@link Class} type of the elements in the array.
* @return an array from the given {@link Collection}. If the {@link Collection} is {@literal null}
* then an empty array of {@link Class component type} is returned.
* @see java.lang.reflect.Array#newInstance(Class, int)
* @see java.util.Collection
*/
@NullSafe
@SuppressWarnings("unchecked")
public static @NotNull T[] toArray(@Nullable Collection collection, @Nullable Class componentType) {
Object[] array = (Object[]) Array.newInstance(componentType, nullSafeSize(collection));
Optional.ofNullable(collection).ifPresent(it -> it.toArray(array));
return (T[]) array;
}
/**
* Returns a {@link String} representation of the {@link Iterable}.
*
* @param iterable {@link Iterable} to render as a {@link String}.
* @return a {@link String} representation of the {@link Iterable}.
* @see org.cp.elements.lang.support.ToStringRenderer
* @see #toString(Iterable, Renderer)
* @see java.lang.Iterable
*/
@NullSafe
public static @NotNull String toString(@Nullable Iterable> iterable) {
return toString(iterable, new ToStringRenderer<>());
}
/**
* Returns a {@link String} representation of the {@link Iterable} rendered with the {@link Renderer}.
*
* @param Class type of the elements in the {@link Iterable}.
* @param iterable {@link Iterable} to render as a {@link String}.
* @param renderer {@link Renderer} used to render the elements in the {@link Iterable} as {@link String}s.
* @return a {@link String} representation of the {@link Iterable}.
* @see org.cp.elements.lang.Renderer
* @see java.lang.Iterable
*/
@NullSafe
public static String toString(@Nullable Iterable iterable, @NotNull Renderer renderer) {
StringBuilder buffer = new StringBuilder("[");
Renderer resolvedRenderer = renderer != null ? renderer : new ToStringRenderer<>();
int count = 0;
for (T element : nullSafeIterable(iterable)) {
buffer.append(count++ > 0 ? StringUtils.COMMA_SPACE_DELIMITER : StringUtils.EMPTY_STRING)
.append(resolvedRenderer.render(element));
}
buffer.append("]");
return buffer.toString();
}
/**
* Transforms the elements in the {@link Collection} using the {@link Transformer}.
*
* @param Class type of the elements in the {@link Collection}.
* @param collection {@link Collection} of elements to transform.
* @param transformer {@link Transformer} used to transform the elements in the {@link Collection}.
* @return the {@link Collection} of elements transformed by the given {@link Transformer}.
* @throws IllegalArgumentException if either the {@link Collection} or {@link Transformer} are null.
* @see org.cp.elements.lang.Transformer
* @see java.util.Collection
*/
public static @NotNull Collection transform(@NotNull Collection collection,
@NotNull Transformer transformer) {
Assert.notNull(collection, "Collection is required");
Assert.notNull(transformer, "Transformer is required");
return collection.stream()
.map(transformer::transform)
.collect(Collectors.toList());
}
/**
* Returns an immutable {@link Iterator} implementation wrapping the given {@link Iterator} to prevent modifications
* through invocations of the {@link Iterator#remove()} method.
*
* @param {@link Class} type of the elements in the {@link Iterator}.
* @param iterator {@link Iterator} to make immutable.
* @return an immutable {@link Iterator} implementation wrapping the given {@link Iterator}.
* @throws IllegalArgumentException if {@link Iterator} is {@literal null}.
* @see java.util.Iterator
*/
public static @NotNull Iterator unmodifiableIterator(@NotNull Iterator iterator) {
Assert.notNull(iterator, "Iterator is required");
return new Iterator<>() {
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public T next() {
return iterator.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException("Iterator is immutable");
}
};
}
}