CollectionUtils.java

  1. /*
  2.  * *************************************************************************************************************************************************************
  3.  *
  4.  * TheseFoolishThings: Miscellaneous utilities
  5.  * http://tidalwave.it/projects/thesefoolishthings
  6.  *
  7.  * Copyright (C) 2009 - 2025 by Tidalwave s.a.s. (http://tidalwave.it)
  8.  *
  9.  * *************************************************************************************************************************************************************
  10.  *
  11.  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
  12.  * You may obtain a copy of the License at
  13.  *
  14.  *     http://www.apache.org/licenses/LICENSE-2.0
  15.  *
  16.  * 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
  17.  * CONDITIONS OF ANY KIND, either express or implied.  See the License for the specific language governing permissions and limitations under the License.
  18.  *
  19.  * *************************************************************************************************************************************************************
  20.  *
  21.  * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
  22.  * git clone https://github.com/tidalwave-it/thesefoolishthings-src
  23.  *
  24.  * *************************************************************************************************************************************************************
  25.  */
  26. package it.tidalwave.util;

  27. import javax.annotation.Nonnull;
  28. import java.util.ArrayList;
  29. import java.util.Collection;
  30. import java.util.Collections;
  31. import java.util.Comparator;
  32. import java.util.List;
  33. import java.util.Optional;
  34. import lombok.AccessLevel;
  35. import lombok.NoArgsConstructor;
  36. import static java.util.Collections.emptyList;

  37. /***************************************************************************************************************************************************************
  38.  *
  39.  * This class contains a bunch of utility methods for manipulating lists.
  40.  *
  41.  * @author  Fabrizio Giudici
  42.  * @since   3.2-ALPHA-13
  43.  * @it.tidalwave.javadoc.stable
  44.  *
  45.  **************************************************************************************************************************************************************/
  46. @NoArgsConstructor(access = AccessLevel.PRIVATE)
  47. public final class CollectionUtils
  48.   {
  49.     /***********************************************************************************************************************************************************
  50.      * Appends a list to an object. The resulting list is mutable.
  51.      *
  52.      * @param     <T>       the type of list items
  53.      * @param     list      the list
  54.      * @param     object    the list to append
  55.      * @return              the list with the appended object
  56.      *
  57.      * @it.tidalwave.javadoc.stable
  58.      **********************************************************************************************************************************************************/
  59.     @Nonnull
  60.     public static <T> List<T> concat (@Nonnull final List<? extends T> list, @Nonnull final T object)
  61.       {
  62.         final List<T> result = new ArrayList<>(list);
  63.         result.add(object);
  64.         return result;
  65.       }

  66.     /***********************************************************************************************************************************************************
  67.      * Returns a concatenation of the given {@link Collection}s.
  68.      *
  69.      * @param     <T>         the static type
  70.      * @param     collections the input collections
  71.      * @return                the concatenation
  72.      *
  73.      * @it.tidalwave.javadoc.stable
  74.      **********************************************************************************************************************************************************/
  75.     @Nonnull @SafeVarargs
  76.     public static <T> List<T> concatAll (@Nonnull final Collection<? extends T>... collections)
  77.       {
  78.         final List<T> result = new ArrayList<>();

  79.         for (final var collection : collections)
  80.           {
  81.             result.addAll(collection);
  82.           }

  83.         return result;
  84.       }

  85.     /***********************************************************************************************************************************************************
  86.      * Reverses a list. The resulting list is mutable.
  87.      *
  88.      * @param     <T>       the type of list items
  89.      * @param     list      the list
  90.      * @return              the reversed list
  91.      *
  92.      * @it.tidalwave.javadoc.stable
  93.      **********************************************************************************************************************************************************/
  94.     @Nonnull
  95.     public static <T> List<T> reversed (@Nonnull final List<? extends T> list)
  96.       {
  97.         final List<T> result = new ArrayList<>(list);
  98.         Collections.reverse(result);
  99.         return result;
  100.       }

  101.     /***********************************************************************************************************************************************************
  102.      * Sorts a list. The resulting list is mutable.
  103.      *
  104.      * @param     <T>       the type of list items
  105.      * @param     list      the list
  106.      * @return              the sorted list
  107.      * @since     3.2-ALPHA-13
  108.      *
  109.      * @it.tidalwave.javadoc.stable
  110.      **********************************************************************************************************************************************************/
  111.     @Nonnull
  112.     public static <T extends Comparable<? super T>> List<T> sorted (@Nonnull final List<? extends T> list)
  113.       {
  114.         final var result = new ArrayList<T>(list);
  115.         Collections.sort(result);
  116.         return result;
  117.       }

  118.     /***********************************************************************************************************************************************************
  119.      * Sorts a list with a given {@link Comparator}. The resulting list is mutable.
  120.      *
  121.      * @param     <T>         the type of list items
  122.      * @param     list        the list
  123.      * @param     comparator  the comparator
  124.      * @return                the sorted list
  125.      * @since     3.2-ALPHA-13
  126.      *
  127.      * @it.tidalwave.javadoc.stable
  128.      **********************************************************************************************************************************************************/
  129.     @Nonnull
  130.     public static <T> List<T> sorted (@Nonnull final List<? extends T> list,
  131.                                       @Nonnull final Comparator<? super T> comparator)
  132.       {
  133.         final var result = new ArrayList<T>(list);
  134.         result.sort(comparator);
  135.         return result;
  136.       }

  137.     /***********************************************************************************************************************************************************
  138.      * Returns the (optional) first element of a list.
  139.      *
  140.      * @param     <T>       the type of list items
  141.      * @param     list      the list
  142.      * @return              the first element
  143.      *
  144.      * @it.tidalwave.javadoc.stable
  145.      **********************************************************************************************************************************************************/
  146.     @Nonnull
  147.     public static <T> Optional<T> optionalHead (@Nonnull final List<? extends T> list)
  148.       {
  149.         return list.isEmpty() ? Optional.empty() : Optional.of(list.get(0));
  150.       }

  151.     /***********************************************************************************************************************************************************
  152.      * Returns the first element of a list.
  153.      *
  154.      * @param     <T>       the type of list items
  155.      * @param     list      the list (cannot be empty)
  156.      * @return              the first element
  157.      * @throws    IllegalArgumentException  if the list is empty
  158.      *
  159.      * @it.tidalwave.javadoc.stable
  160.      **********************************************************************************************************************************************************/
  161.     @Nonnull
  162.     public static <T> T head (@Nonnull final List<? extends T> list)
  163.       {
  164.         if (list.isEmpty())
  165.           {
  166.             throw new IllegalArgumentException("List is empty");
  167.           }

  168.         return list.get(0);
  169.       }

  170.     /***********************************************************************************************************************************************************
  171.      * Returns the tail element of a list, that is a list without the first element. The tail of an empty list is an
  172.      * empty list. The resulting list is mutable.
  173.      *
  174.      * @param     <T>       the type of list items
  175.      * @param     list      the list
  176.      * @return              the tail of the list
  177.      *
  178.      * @it.tidalwave.javadoc.stable
  179.      **********************************************************************************************************************************************************/
  180.     @Nonnull
  181.     public static <T> List<T> tail (@Nonnull final List<? extends T> list)
  182.       {
  183.         return new ArrayList<>(list.subList(1, list.size()));
  184.       }

  185.     /***********************************************************************************************************************************************************
  186.      * Return a sublist of the original {@link List}, from the given {@code from} and {@code to} index (not included).
  187.      * If the {@code from} index is negative and/or the {@code to} index is lower than the {@code from} index or if an
  188.      * attempt is made to read before the start or past the end of the list, truncation silently occurs.
  189.      *
  190.      * @param     <T>             the static type
  191.      * @param     list            the original list
  192.      * @param     from            the first index (included)
  193.      * @param     to              the last index (excluded)
  194.      * @return                    the sublist
  195.      * @since     3.2-ALPHA-17
  196.      **********************************************************************************************************************************************************/
  197.     @Nonnull
  198.     public static <T> List<T> safeSubList (@Nonnull final List<? extends T> list, final int from, final int to)
  199.       {
  200.         final var safeFrom = Math.max(from, 0);
  201.         final var safeTo = Math.min(list.size(), to);
  202.         return (safeFrom >= safeTo) ? emptyList() : new ArrayList<>(list.subList(safeFrom, safeTo));
  203.       }

  204.     /***********************************************************************************************************************************************************
  205.      * Splits a given {@link List} at a set of boundaries. Each boundary is the starting point of a sublist to be
  206.      * returned.
  207.      *
  208.      * @param     <T>             the static type
  209.      * @param     list            the original list
  210.      * @param     boundaries      the boundaries
  211.      * @return                    a list of sublists
  212.      * @since     3.2-ALPHA-17
  213.      **********************************************************************************************************************************************************/
  214.     @Nonnull
  215.     public static <T> List<List<T>> split (@Nonnull final List<? extends T> list, final int ... boundaries)
  216.       {
  217.         final var result = new ArrayList<List<T>>();

  218.         for (var i = 0; i < boundaries.length - 1; i++)
  219.           {
  220.             result.add(safeSubList(list, boundaries[i], boundaries[i + 1]));
  221.           }

  222.         return result;
  223.       }
  224.   }