/*
 * Copyright 2017-2020 original 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
 *
 * https://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 io.micronaut.core.util;

import io.micronaut.core.annotation.UsedByGeneratedCode;
import io.micronaut.core.convert.ConversionService;

import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.lang.reflect.Constructor;
import java.util.*;

Utility methods for working with Collection types

.
Author:Graeme Rocher
Since:1.0
/** * <p>Utility methods for working with {@link java.util.Collection} types</p>. * * @author Graeme Rocher * @since 1.0 */
public class CollectionUtils {
Is the given type an iterable or map type.
Params:
  • type – The type
Returns:True if it is iterable or map
Since:2.0.0
/** * Is the given type an iterable or map type. * @param type The type * @return True if it is iterable or map * @since 2.0.0 */
public static boolean isIterableOrMap(Class<?> type) { return type != null && (Iterable.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type)); }
Null safe empty check.
Params:
  • map – The map
Returns:True if it is empty or null
/** * Null safe empty check. * * @param map The map * @return True if it is empty or null */
public static boolean isEmpty(@Nullable Map map) { return map == null || map.isEmpty(); }
Null safe not empty check.
Params:
  • map – The ,ap
Returns:True if it is not null and not empty
/** * Null safe not empty check. * * @param map The ,ap * @return True if it is not null and not empty */
public static boolean isNotEmpty(@Nullable Map map) { return map != null && !map.isEmpty(); }
Null safe empty check.
Params:
  • collection – The collection
Returns:True if it is empty or null
/** * Null safe empty check. * * @param collection The collection * @return True if it is empty or null */
public static boolean isEmpty(@Nullable Collection collection) { return collection == null || collection.isEmpty(); }
Null safe not empty check.
Params:
  • collection – The collection
Returns:True if it is not null and not empty
/** * Null safe not empty check. * * @param collection The collection * @return True if it is not null and not empty */
public static boolean isNotEmpty(@Nullable Collection collection) { return collection != null && !collection.isEmpty(); }

Attempts to convert a collection to the given iterabable type

.
Params:
  • iterableType – The iterable type
  • collection – The collection
Type parameters:
  • <T> – The collection generic type
Returns:An Optional of the converted type
/** * <p>Attempts to convert a collection to the given iterabable type</p>. * * @param iterableType The iterable type * @param collection The collection * @param <T> The collection generic type * @return An {@link Optional} of the converted type */
public static <T> Optional<Iterable<T>> convertCollection(Class<? extends Iterable<T>> iterableType, Collection<T> collection) { if (iterableType.isInstance(collection)) { return Optional.of(collection); } if (iterableType.equals(Set.class)) { return Optional.of(new HashSet<>(collection)); } if (iterableType.equals(Queue.class)) { return Optional.of(new LinkedList<>(collection)); } if (iterableType.equals(List.class)) { return Optional.of(new ArrayList<>(collection)); } if (!iterableType.isInterface()) { try { Constructor<? extends Iterable<T>> constructor = iterableType.getConstructor(Collection.class); return Optional.of(constructor.newInstance(collection)); } catch (Throwable e) { return Optional.empty(); } } return Optional.empty(); }
Create a LinkedHashMap from an array of values.
Params:
  • values – The values
Returns:The created map
/** * Create a {@link LinkedHashMap} from an array of values. * * @param values The values * @return The created map */
@UsedByGeneratedCode public static Map mapOf(Object... values) { int len = values.length; if (len % 2 != 0) { throw new IllegalArgumentException("Number of arguments should be an even number representing the keys and values"); } Map answer = new LinkedHashMap(len / 2); int i = 0; while (i < values.length - 1) { answer.put(values[i++], values[i++]); } return answer; }
Convert an Iterator to a Set.
Params:
  • iterator – The iterator
Type parameters:
  • <T> – The type
Returns:The set
/** * Convert an {@link Iterator} to a {@link Set}. * * @param iterator The iterator * @param <T> The type * @return The set */
public static <T> Set<T> iteratorToSet(Iterator<T> iterator) { Set<T> set = new HashSet<>(); while (iterator.hasNext()) { set.add(iterator.next()); } return set; }
Convert an Enumeration to a Set.
Params:
  • enumeration – The iterator
Type parameters:
  • <T> – The type
Returns:The set
/** * Convert an {@link Enumeration} to a {@link Set}. * * @param enumeration The iterator * @param <T> The type * @return The set */
public static <T> Set<T> enumerationToSet(Enumeration<T> enumeration) { Set<T> set = new HashSet<>(); while (enumeration.hasMoreElements()) { set.add(enumeration.nextElement()); } return set; }
Convert an Enumeration to a Iterable.
Params:
  • enumeration – The iterator
Type parameters:
  • <T> – The type
Returns:The set
/** * Convert an {@link Enumeration} to a {@link Iterable}. * * @param enumeration The iterator * @param <T> The type * @return The set */
public static @NonNull <T> Iterable<T> enumerationToIterable(@Nullable Enumeration<T> enumeration) { if (enumeration == null) { return Collections.emptyList(); } return () -> new Iterator<T>() { @Override public boolean hasNext() { return enumeration.hasMoreElements(); } @Override public T next() { return enumeration.nextElement(); } }; }
Creates a set of the given objects.
Params:
  • objects – The objects
Type parameters:
  • <T> – The type
Returns:The set
/** * Creates a set of the given objects. * * @param objects The objects * @param <T> The type * @return The set */
public static <T> Set<T> setOf(T... objects) { if (objects == null || objects.length == 0) { return new HashSet<>(0); } return new HashSet<>(Arrays.asList(objects)); }
Produce a string representation of the given iterable.
Params:
  • iterable – The iterable
Returns:The string representation
/** * Produce a string representation of the given iterable. * * @param iterable The iterable * @return The string representation */
public static String toString(Iterable<?> iterable) { return toString(",", iterable); }
Produce a string representation of the given iterable.
Params:
  • delimiter – The delimiter
  • iterable – The iterable
Returns:The string representation
/** * Produce a string representation of the given iterable. * * @param delimiter The delimiter * @param iterable The iterable * @return The string representation */
public static String toString(String delimiter, Iterable<?> iterable) { StringBuilder builder = new StringBuilder(); Iterator<?> i = iterable.iterator(); while (i.hasNext()) { Object o = i.next(); if (o == null) { continue; } else { if (CharSequence.class.isInstance(o)) { builder.append(o.toString()); } else { Optional<String> converted = ConversionService.SHARED.convert(o, String.class); converted.ifPresent(builder::append); } } if (i.hasNext()) { builder.append(delimiter); } } return builder.toString(); }
Converts an Iterable to a List.
Params:
  • iterable – The iterable
Type parameters:
  • <T> – The generic type
Returns:The list
/** * Converts an {@link Iterable} to a {@link List}. * * @param iterable The iterable * @param <T> The generic type * @return The list */
public static <T> List<T> iterableToList(Iterable<T> iterable) { if (iterable == null) { return Collections.emptyList(); } if (iterable instanceof List) { return (List<T>) iterable; } Iterator<T> i = iterable.iterator(); if (i.hasNext()) { List<T> list = new ArrayList<>(); while (i.hasNext()) { list.add(i.next()); } return list; } return Collections.emptyList(); }
Converts an Iterable to a Set.
Params:
  • iterable – The iterable
Type parameters:
  • <T> – The generic type
Returns:The set
/** * Converts an {@link Iterable} to a {@link Set}. * * @param iterable The iterable * @param <T> The generic type * @return The set */
public static <T> Set<T> iterableToSet(Iterable<T> iterable) { if (iterable == null) { return Collections.emptySet(); } if (iterable instanceof Set) { return (Set<T>) iterable; } Iterator<T> i = iterable.iterator(); if (i.hasNext()) { Set<T> list = new HashSet<>(); while (i.hasNext()) { list.add(i.next()); } return list; } return Collections.emptySet(); }
Params:
  • list – The list
Type parameters:
  • <T> – The generic type
Returns:A non-null unmodifiable list
/** * Null safe version of {@link Collections#unmodifiableList(List)}. * * @param list The list * @param <T> The generic type * @return A non-null unmodifiable list */
public static @NonNull <T> List<T> unmodifiableList(@Nullable List<T> list) { if (isEmpty(list)) { return Collections.emptyList(); } return Collections.unmodifiableList(list); }
Returns the last element of a collection.
Params:
  • collection – The collection
Type parameters:
  • <T> – The generic type
Returns:The last element of a collection or null
/** * Returns the last element of a collection. * * @param collection The collection * @param <T> The generic type * @return The last element of a collection or null */
public static @Nullable <T> T last(@NonNull Collection<T> collection) { if (collection instanceof List) { List<T> list = (List<T>) collection; final int s = list.size(); if (s > 0) { return list.get(s - 1); } else { return null; } } else if (collection instanceof Deque) { final Iterator<T> i = ((Deque<T>) collection).descendingIterator(); if (i.hasNext()) { return i.next(); } return null; } else if (collection instanceof NavigableSet) { final Iterator<T> i = ((NavigableSet<T>) collection).descendingIterator(); if (i.hasNext()) { return i.next(); } return null; } else { T result = null; for (T t : collection) { result = t; } return result; } } }