CollectionUtils.java

  1. /*
  2.  * *********************************************************************************************************************
  3.  *
  4.  * TheseFoolishThings: Miscellaneous utilities
  5.  * http://tidalwave.it/projects/thesefoolishthings
  6.  *
  7.  * Copyright (C) 2009 - 2023 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
  12.  * the License. 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
  17.  * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
  18.  * specific language governing permissions and limitations under the License.
  19.  *
  20.  * *********************************************************************************************************************
  21.  *
  22.  * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
  23.  * git clone https://github.com/tidalwave-it/thesefoolishthings-src
  24.  *
  25.  * *********************************************************************************************************************
  26.  */
  27. package it.tidalwave.util;

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

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

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

  84.         for (final var collection : collections)
  85.           {
  86.             result.addAll(collection);
  87.           }

  88.         return result;
  89.       }

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

  108.     /*******************************************************************************************************************
  109.      *
  110.      * Sorts a list. The resulting list is mutable.
  111.      *
  112.      * @param     <T>       the type of list items
  113.      * @param     list      the list
  114.      * @return              the sorted list
  115.      * @since     3.2-ALPHA-13
  116.      *
  117.      * @it.tidalwave.javadoc.stable
  118.      *
  119.      ******************************************************************************************************************/
  120.     @Nonnull
  121.     public static <T extends Comparable<? super T>> List<T> sorted (@Nonnull final List<? extends T> list)
  122.       {
  123.         final var result = new ArrayList<T>(list);
  124.         Collections.sort(result);
  125.         return result;
  126.       }

  127.     /*******************************************************************************************************************
  128.      *
  129.      * Sorts a list with a given {@link Comparator}. The resulting list is mutable.
  130.      *
  131.      * @param     <T>         the type of list items
  132.      * @param     list        the list
  133.      * @param     comparator  the comparator
  134.      * @return                the sorted list
  135.      * @since     3.2-ALPHA-13
  136.      *
  137.      * @it.tidalwave.javadoc.stable
  138.      *
  139.      ******************************************************************************************************************/
  140.     @Nonnull
  141.     public static <T> List<T> sorted (@Nonnull final List<? extends T> list,
  142.                                       @Nonnull final Comparator<? super T> comparator)
  143.       {
  144.         final var result = new ArrayList<T>(list);
  145.         result.sort(comparator);
  146.         return result;
  147.       }

  148.     /*******************************************************************************************************************
  149.      *
  150.      * Returns the (optional) first element of a list.
  151.      *
  152.      * @param     <T>       the type of list items
  153.      * @param     list      the list
  154.      * @return              the first element
  155.      *
  156.      * @it.tidalwave.javadoc.stable
  157.      *
  158.      ******************************************************************************************************************/
  159.     @Nonnull
  160.     public static <T> Optional<T> optionalHead (@Nonnull final List<? extends T> list)
  161.       {
  162.         return list.isEmpty() ? Optional.empty() : Optional.of(list.get(0));
  163.       }

  164.     /*******************************************************************************************************************
  165.      *
  166.      * Returns the first element of a list.
  167.      *
  168.      * @param     <T>       the type of list items
  169.      * @param     list      the list (cannot be empty)
  170.      * @return              the first element
  171.      * @throws    IllegalArgumentException  if the list is empty
  172.      *
  173.      * @it.tidalwave.javadoc.stable
  174.      *
  175.      ******************************************************************************************************************/
  176.     @Nonnull
  177.     public static <T> T head (@Nonnull final List<? extends T> list)
  178.       {
  179.         if (list.isEmpty())
  180.           {
  181.             throw new IllegalArgumentException("List is empty");
  182.           }

  183.         return list.get(0);
  184.       }

  185.     /*******************************************************************************************************************
  186.      *
  187.      * Returns the tail element of a list, that is a list without the first element. The tail of an empty list is an
  188.      * empty list. The resulting list is mutable.
  189.      *
  190.      * @param     <T>       the type of list items
  191.      * @param     list      the list
  192.      * @return              the tail of the list
  193.      *
  194.      * @it.tidalwave.javadoc.stable
  195.      *
  196.      ******************************************************************************************************************/
  197.     @Nonnull
  198.     public static <T> List<T> tail (@Nonnull final List<? extends T> list)
  199.       {
  200.         return new ArrayList<>(list.subList(1, list.size()));
  201.       }

  202.     /*******************************************************************************************************************
  203.      *
  204.      * Return a sublist of the original {@link List}, from the given {@code from} and {@code to} index (not included).
  205.      * If the {@code from} index is negative and/or the {@code to} index is lower than the {@code from} index or if an
  206.      * attempt is made to read before the start or past the end of the list, truncation silently occurs.
  207.      *
  208.      * @param     <T>             the static type
  209.      * @param     list            the original list
  210.      * @param     from            the first index (included)
  211.      * @param     to              the last index (excluded)
  212.      * @return                    the sublist
  213.      * @since     3.2-ALPHA-17
  214.      *
  215.      ******************************************************************************************************************/
  216.     @Nonnull
  217.     public static <T> List<T> safeSubList (@Nonnull final List<? extends T> list, final int from, final int to)
  218.       {
  219.         final var safeFrom = Math.max(from, 0);
  220.         final var safeTo = Math.min(list.size(), to);
  221.         return (safeFrom >= safeTo) ? emptyList() : new ArrayList<>(list.subList(safeFrom, safeTo));
  222.       }

  223.     /*******************************************************************************************************************
  224.      *
  225.      * Splits a given {@link List} at a set of boundaries. Each boundary is the starting point of a sublist to be
  226.      * returned.
  227.      *
  228.      * @param     <T>             the static type
  229.      * @param     list            the original list
  230.      * @param     boundaries      the boundaries
  231.      * @return                    a list of sublists
  232.      * @since     3.2-ALPHA-17
  233.      *
  234.      ******************************************************************************************************************/
  235.     @Nonnull
  236.     public static <T> List<List<T>> split (@Nonnull final List<? extends T> list, final int ... boundaries)
  237.       {
  238.         final var result = new ArrayList<List<T>>();

  239.         for (var i = 0; i < boundaries.length - 1; i++)
  240.           {
  241.             result.add(safeSubList(list, boundaries[i], boundaries[i + 1]));
  242.           }

  243.         return result;
  244.       }
  245.   }