001package co.codewizards.cloudstore.core.util;
002
003import static java.util.Objects.*;
004
005import java.util.ArrayList;
006import java.util.Collection;
007import java.util.Collections;
008import java.util.Iterator;
009import java.util.LinkedHashSet;
010import java.util.List;
011import java.util.Set;
012
013public final class CollectionUtil {
014
015        private CollectionUtil() {
016        }
017
018        /**
019         * Splits a given {@code Set} into multiple {@code Set}s, each with the maximum size specified.
020         * <p>
021         * For example, imagine a {@code Set} with 26 elements. Invoking this method with {@code maxSize == 10}
022         * will cause a resulting {@code List} having 3 {@code Set} elements. The first 2 of the {@code Set}
023         * elements each have 10 elements, while the 3rd one will have only 6 elements.
024         * <p>
025         * Please note that the order is maintained ({@link LinkedHashSet} is used internally for each
026         * segment-{@code Set}).
027         *
028         * @param inputSet the {@code Set} to be split. Must not be <code>null</code>. This {@code Set} is not
029         * modified in any way by this method.
030         * @param maxSize the maximum size of each resulting segment-{@code Set}. Must be greater than 0.
031         * @return a {@code List} containing all elements from the given {@code inputSet} in the same order,
032         * grouped in groups each not greater than {@code maxSize}. Never <code>null</code>.
033         * @see #splitList(List, int)
034         */
035        public static <E> List<Set<E>> splitSet(final Set<E> inputSet, final int maxSize) {
036                requireNonNull(inputSet, "inputSet");
037                if (maxSize < 1)
038                        throw new IllegalArgumentException("maxSize < 1");
039
040                final List<Set<E>> result = new ArrayList<>(inputSet.size() / maxSize + 1);
041                Set<E> current = null;
042                for (final E element : inputSet) {
043                        if (current == null || current.size() >= maxSize) {
044                                current = new LinkedHashSet<E>(maxSize);
045                                result.add(current);
046                        }
047                        current.add(element);
048                }
049                return result;
050        }
051
052        /**
053         * Splits a given {@code List} into multiple {@code List}s, each with the maximum size specified.
054         * <p>
055         * For example, imagine a {@code List} with 26 elements. Invoking this method with {@code maxSize == 10}
056         * will cause a resulting {@code List} having 3 {@code List} elements. The first 2 of the {@code List}
057         * elements each have 10 elements, while the 3rd one will have only 6 elements.
058         * <p>
059         * Please note that the order is maintained.
060         *
061         * @param inputList the {@code List} to be split. Must not be <code>null</code>. This {@code List} is not
062         * modified in any way by this method.
063         * @param maxSize the maximum size of each resulting segment-{@code List}. Must be greater than 0.
064         * @return a {@code List} containing all elements from the given {@code inputList} in the same order,
065         * grouped in groups each not greater than {@code maxSize}. Never <code>null</code>.
066         * @see #splitSet(Set, int)
067         */
068        public static <E> List<List<E>> splitList(final List<E> inputList, final int maxSize) {
069                requireNonNull(inputList, "inputList");
070                if (maxSize < 1)
071                        throw new IllegalArgumentException("maxSize < 1");
072
073                final List<List<E>> result = new ArrayList<>(inputList.size() / maxSize + 1);
074                List<E> current = null;
075                for (final E element : inputList) {
076                        if (current == null || current.size() >= maxSize) {
077                                current = new ArrayList<E>(maxSize);
078                                result.add(current);
079                        }
080                        current.add(element);
081                }
082                return result;
083        }
084
085        public static <E> List<E> nullToEmpty(final List<E> list) {
086                return list == null ? Collections.<E>emptyList() : list;
087        }
088
089        public static <E> Set<E> nullToEmpty(final Set<E> set) {
090                return set == null ? Collections.<E>emptySet() : set;
091        }
092
093        public static <E> Collection<E> nullToEmpty(final Collection<E> collection) {
094                return collection == null ? Collections.<E>emptyList() : collection;
095        }
096
097        public static <E> Iterator<E> nullToEmpty(final Iterator<E> iterator) {
098                return iterator == null ? Collections.<E>emptyList().iterator() : iterator;
099        }
100
101        @SafeVarargs
102        public static <E> List<E> asListWithoutNullElements(final E... elements) {
103                if (elements == null)
104                        return Collections.emptyList();
105
106                final ArrayList<E> result = new ArrayList<>(elements.length);
107                for (final E element : elements) {
108                        if (element != null)
109                                result.add(element);
110                }
111                result.trimToSize();
112                return Collections.unmodifiableList(result);
113        }
114}