All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.helger.commons.collection.impl.ICommonsIterable Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2014-2024 Philip Helger (www.helger.com)
 * philip[at]helger[dot]com
 *
 * 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 com.helger.commons.collection.impl;

import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.ObjIntConsumer;
import java.util.function.Predicate;

import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import com.helger.commons.collection.CollectionHelper;
import com.helger.commons.collection.IteratorHelper;
import com.helger.commons.functional.IThrowingConsumer;
import com.helger.commons.state.EContinue;

/**
 * Extended version of {@link Iterable} with some additional default methods.
 *
 * @author Philip Helger
 * @param 
 *        The data type to iterate
 */
public interface ICommonsIterable  extends Iterable 
{
  /**
   * Special forEach that takes an {@link ObjIntConsumer} which is provided the
   * value AND the index.
   *
   * @param aConsumer
   *        The consumer to use. May not be null.
   */
  default void forEachByIndex (@Nonnull final ObjIntConsumer  aConsumer)
  {
    int nIndex = 0;
    for (final ELEMENTTYPE aItem : this)
    {
      aConsumer.accept (aItem, nIndex);
      ++nIndex;
    }
  }

  /**
   * A special version of {@link #forEach(Consumer)} that can break iteration if
   * a certain requirement is fulfilled.
   *
   * @param aConsumer
   *        The consumer to be invoked. May not be null.
   * @return {@link EContinue#BREAK} if iteration was stopped,
   *         {@link EContinue#CONTINUE} otherwise.
   */
  @Nonnull
  default EContinue forEachBreakable (@Nonnull final Function  aConsumer)
  {
    Objects.requireNonNull (aConsumer);
    for (final ELEMENTTYPE aElement : this)
      if (aConsumer.apply (aElement).isBreak ())
        return EContinue.BREAK;
    return EContinue.CONTINUE;
  }

  /**
   * A special version of {@link #forEach(Consumer)} where a consumer can throw
   * an exception.
   *
   * @param aConsumer
   *        The consumer to be invoked. May not be null.
   * @throws EXTYPE
   *         If one of the consumer throws this exception
   * @param 
   *        the type of Exception to be thrown
   * @since 10.0.0
   */
  default  void forEachThrowing (@Nonnull final IThrowingConsumer  aConsumer) throws EXTYPE
  {
    for (final ELEMENTTYPE aCallback : this)
      aConsumer.accept (aCallback);
  }

  /**
   * Find all elements matching the supplied filter and invoke the provided
   * consumer for each matching element.
   *
   * @param aFilter
   *        The filter to be applied. May be null.
   * @param aConsumer
   *        The consumer to be invoked for all matching elements. May not be
   *        null.
   */
  default void findAll (@Nullable final Predicate  aFilter, @Nonnull final Consumer  aConsumer)
  {
    CollectionHelper.findAll (this, aFilter, aConsumer);
  }

  /**
   * Convert all elements using the provided function and invoke the provided
   * consumer for all mapped elements.
   *
   * @param aMapper
   *        The mapping function to be executed for all elements. May not be
   *        null.
   * @param aConsumer
   *        The consumer to be invoked for all mapped elements. May not be
   *        null.
   * @param 
   *        The destination type to be mapped to
   */
  default  void findAllMapped (@Nonnull final Function  aMapper,
                                        @Nonnull final Consumer  aConsumer)
  {
    CollectionHelper.findAllMapped (this, aMapper, aConsumer);
  }

  /**
   * Find all elements matching the provided filter, convert the matching
   * elements using the provided function and invoke the provided consumer for
   * all mapped elements.
   *
   * @param aFilter
   *        The filter to be applied. May be null.
   * @param aMapper
   *        The mapping function to be executed for all matching elements. May
   *        not be null.
   * @param aConsumer
   *        The consumer to be invoked for all matching mapped elements. May not
   *        be null.
   * @param 
   *        The destination type to be mapped to
   */
  default  void findAllMapped (@Nullable final Predicate  aFilter,
                                        @Nonnull final Function  aMapper,
                                        @Nonnull final Consumer  aConsumer)
  {
    CollectionHelper.findAllMapped (this, aFilter, aMapper, aConsumer);
  }

  /**
   * Convert all elements using the provided function, find all mapped elements
   * matching the provided filter and invoke the provided consumer for all
   * matching elements.
   *
   * @param aMapper
   *        The mapping function to be executed for all matching elements. May
   *        not be null.
   * @param aFilter
   *        The filter to be applied. May be null.
   * @param aConsumer
   *        The consumer to be invoked for all matching mapped elements. May not
   *        be null.
   * @param 
   *        The destination type to be mapped to
   * @since 8.5.2
   */
  default  void findAllMapped (@Nonnull final Function  aMapper,
                                        @Nullable final Predicate  aFilter,
                                        @Nonnull final Consumer  aConsumer)
  {
    CollectionHelper.findAllMapped (this, aMapper, aFilter, aConsumer);
  }

  /**
   * Find all elements that are instanceOf the provided class and
   * invoke the provided consumer for all matching elements. This is a special
   * implementation of {@link #findAllMapped(Predicate, Function, Consumer)}.
   *
   * @param aDstClass
   *        The class of which all elements should be find. May not be
   *        null.
   * @param aConsumer
   *        The consumer to be invoked for all instances of the provided class.
   *        May not be null.
   * @param 
   *        The destination type to be casted to
   */
  default  void findAllInstanceOf (@Nonnull final Class  aDstClass,
                                                                @Nonnull final Consumer  aConsumer)
  {
    findAllMapped (aDstClass::isInstance, aDstClass::cast, aConsumer);
  }

  /**
   * Find the first element that matches the provided filter. If no element
   * matches the provided filter or if the collection is empty,
   * null is returned by default. If this collection does not
   * maintain order (like Set) it is undefined which value is returned.
   *
   * @param aFilter
   *        The filter to be applied. May be null.
   * @return null if no element matches the filter or if the
   *         collection is empty, the first matching element otherwise.
   * @see #findFirst(Predicate, Object)
   */
  @Nullable
  default ELEMENTTYPE findFirst (@Nullable final Predicate  aFilter)
  {
    return findFirst (aFilter, null);
  }

  /**
   * Find the first element that matches the provided filter. If no element
   * matches the provided filter or if the collection is empty, the provided
   * default value is returned. If this collection does not maintain order (like
   * Set) it is undefined which value is returned.
   *
   * @param aFilter
   *        The filter to be applied. May be null.
   * @param aDefault
   *        The default value to be returned if no element matches. May be
   *        null.
   * @return The provided default value if no element matches the filter or if
   *         the collection is empty, the first matching element otherwise.
   * @see #findFirst(Predicate)
   */
  @Nullable
  default ELEMENTTYPE findFirst (@Nullable final Predicate  aFilter, @Nullable final ELEMENTTYPE aDefault)
  {
    return CollectionHelper.findFirst (this, aFilter, aDefault);
  }

  /**
   * Find the first element that matches the provided filter and convert it
   * using the provided mapper. If no element matches the provided filter or if
   * the collection is empty, null is returned by default. If this
   * collection does not maintain order (like Set) it is undefined which value
   * is returned.
   *
   * @param aFilter
   *        The filter to be applied. May be null.
   * @param aMapper
   *        The mapping function to be executed for the first matching element.
   *        May not be null.
   * @return null if no element matches the filter or if the
   *         collection is empty, the first matching element otherwise.
   * @param 
   *        The destination type to be mapped to
   * @see #findFirstMapped(Predicate, Function, Object)
   */
  @Nullable
  default  DSTTYPE findFirstMapped (@Nullable final Predicate  aFilter,
                                             @Nonnull final Function  aMapper)
  {
    return findFirstMapped (aFilter, aMapper, null);
  }

  /**
   * Find the first element that matches the provided filter and convert it
   * using the provided mapper. If no element matches the provided filter or if
   * the collection is empty, the provided default value is returned. If this
   * collection does not maintain order (like Set) it is undefined which value
   * is returned.
   *
   * @param aFilter
   *        The filter to be applied. May be null.
   * @param aMapper
   *        The mapping function to be executed for the first matching element.
   *        May not be null.
   * @param aDefault
   *        The default value to be returned if no element matches. May be
   *        null.
   * @return The provided default value if no element matches the filter or if
   *         the collection is empty, the first matching element otherwise.
   * @param 
   *        The destination type to be mapped to
   * @see #findFirstMapped(Predicate, Function)
   */
  @Nullable
  default  DSTTYPE findFirstMapped (@Nullable final Predicate  aFilter,
                                             @Nonnull final Function  aMapper,
                                             @Nullable final DSTTYPE aDefault)
  {
    return CollectionHelper.findFirstMapped (this, aFilter, aMapper, aDefault);
  }

  /**
   * Check if this collection contains any (=at least one) element matching the
   * provided filter.
   *
   * @param aFilter
   *        The filter to be applied. May be null.
   * @return true if the container is not empty and at least one
   *         element matches the provided filter, false otherwise.
   *         If no filter is provided the response is the same as
   *         {@link ICommonsCollection#isNotEmpty()}.
   */
  default boolean containsAny (@Nullable final Predicate  aFilter)
  {
    return CollectionHelper.containsAny (this, aFilter);
  }

  /**
   * Check if this collection contains no (=zero) element matching the provided
   * filter.
   *
   * @param aFilter
   *        The filter to be applied. May be null.
   * @return true if the container is empty or if no element
   *         matches the provided filter, false otherwise. If no
   *         filter is provided, this is the same as
   *         {@link ICommonsCollection#isEmpty()}.
   */
  default boolean containsNone (@Nullable final Predicate  aFilter)
  {
    return CollectionHelper.containsNone (this, aFilter);
  }

  /**
   * Check if this collection contains only (=all) elements matching the
   * provided filter. If this collection is empty, it does not fulfill this
   * requirement! If no filter is provided the return value is identical to
   * {@link ICommonsCollection#isNotEmpty()}.
   *
   * @param aFilter
   *        The filter to be applied. May be null.
   * @return true if this collection is not empty and all elements
   *         matching the filter or if no filter is provided and this collection
   *         is not empty, false otherwise. If no filter is
   *         supplied the return value is identical to
   *         {@link ICommonsCollection#isNotEmpty()}.
   */
  default boolean containsOnly (@Nonnull final Predicate  aFilter)
  {
    return CollectionHelper.containsOnly (this, aFilter);
  }

  /**
   * Retrieve the size of this {@link Iterable}. This method does by default
   * iterate all elements. Please provide a more efficient solution. If this is
   * a collection, consider using size() instead.
   *
   * @return The number objects contained. Always ≥ 0.
   */
  @Nonnegative
  default int getCount ()
  {
    return IteratorHelper.getSize (iterator ());
  }

  /**
   * Count the number of elements in this iterable matching the provided filter.
   *
   * @param aFilter
   *        The filter to be applied. May be null.
   * @return The number of matching elements. Always ≥ 0. If no filter is
   *         provided this is the same as {@link #getCount()}.
   */
  @Nonnegative
  default int getCount (@Nullable final Predicate  aFilter)
  {
    if (aFilter == null)
      return getCount ();

    int ret = 0;
    for (final ELEMENTTYPE aElement : this)
      if (aFilter.test (aElement))
        ret++;
    return ret;
  }

  /**
   * Find the first index where the provided filter matches.
   *
   * @param aFilter
   *        The filter to use. May not be null.
   * @return -1 if no element matches the filter, the 0-based index otherwise.
   * @since 9.3.3
   */
  @Nonnegative
  default int findFirstIndex (@Nonnull final Predicate  aFilter)
  {
    int nIndex = 0;
    for (final ELEMENTTYPE aElement : this)
    {
      if (aFilter.test (aElement))
        return nIndex;
      nIndex++;
    }
    return -1;
  }

  /**
   * Find the last index where the provided filter matches.
   *
   * @param aFilter
   *        The filter to use. May not be null.
   * @return -1 if no element matches the filter, the 0-based index otherwise.
   * @since 9.3.3
   */
  @Nonnegative
  default int findLastIndex (@Nonnull final Predicate  aFilter)
  {
    int ret = -1;
    int nIndex = 0;
    for (final ELEMENTTYPE aElement : this)
    {
      if (aFilter.test (aElement))
        ret = nIndex;
      nIndex++;
    }
    return ret;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy