Package groovy.util

# Class Iterators

java.lang.Object
groovy.util.Iterators

public class Iterators extends Object
Provides some iterator based generators.

Since:
  5.0.0

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `Iterators()`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `static <K, T> Iterator<Map<K,T>>`
  `combine(Map<K,? extends Iterator<T>> map)`
  An iterator returning a map for each combination of elements the iterator sources.
  `static <K, T> Iterator<Map<K,T>>`
  `combine(Map<K,? extends Iterator<T>> map, boolean fairOrdering)`
  An iterator returning a map for each combination of elements the iterator sources.
  `static <T> Iterator<T>`
  `generate(Supplier<? extends T> next)`
  An iterator providing infinite elements using a Supplier.
  `static <T> Iterator<T>`
  `iterate(T seed, UnaryOperator<T> advance)`
  An iterator providing infinite elements using a seed and a UnaryOperator to produce the next element from the previous one.

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Constructor Details

  - ### Iterators

    public Iterators()

- ## Method Details

  - ### iterate

    public static <T> Iterator<T> iterate(T seed, UnaryOperator<T> advance)
    An iterator providing infinite elements using a seed and a UnaryOperator to produce the next element from the previous one. Since the iterator produces infinite elements, you should have some means to stop requesting elements external to this iterator.

         assert Iterators.iterate(0, n -> n + 2).take(5).toList() == [0, 2, 4, 6, 8]
         assert Iterators.iterate('a', String::next).take(6).join() == 'abcdef'

    Parameters:
      `seed` - the first element
      `advance` - an operator returning the next element given the current (previous) one.
    Returns:
      the iterator of produced elements
    See Also:
      - `Stream.iterate(Object, UnaryOperator)`

  - ### generate

    public static <T> Iterator<T> generate(Supplier<? extends T> next)
    An iterator providing infinite elements using a Supplier. Since the iterator produces infinite elements, you should have some means to stop requesting elements external to this iterator.

         import java.util.function.Supplier
         var r = new Random()
         assert Iterators.generate({ r.nextInt(10) } as Supplier).take(3).collect() ==~ /\[\d, \d, \d\]/

    Parameters:
      `next` - the supplier of elements
    Returns:
      the iterator of generated values
    See Also:
      - `Stream.generate(Supplier)`

  - ### combine

    public static <K, T> Iterator<Map<K,T>> combine(Map<K,? extends Iterator<T>> map)
    An iterator returning a map for each combination of elements the iterator sources. If one of the iterators is infinite, the produced elements will be infinite and will need to be appropriately handled. By necessity, elements from the iterators are cached, so you should use `Iterables.combine(Map)` if you have existing iterables as this will be more efficient.

         assert Iterators.combine(x: (1..2).iterator(), y: ('a'..'c').iterator()).collect().toString()
             == '[[x:1, y:a], [x:1, y:b], [x:1, y:c], [x:2, y:a], [x:2, y:b], [x:2, y:c]]'
         assert Iterators.combine(x: (1..3).iterator(), y: ('a'..'b').iterator()).collect().toString()
             == '[[x:1, y:a], [x:1, y:b], [x:2, y:a], [x:2, y:b], [x:3, y:a], [x:3, y:b]]'

    Parameters:
      `map` - the named source iterators
    Returns:
      the output iterator of named combinations

  - ### combine

    public static <K, T> Iterator<Map<K,T>> combine(Map<K,? extends Iterator<T>> map, boolean fairOrdering)
    An iterator returning a map for each combination of elements the iterator sources. If one of the iterators is infinite, the produced elements will be infinite and will need to be appropriately handled. By necessity, elements from the iterators are cached, so you should use `Iterables.combine(Map)` if you have existing iterables as this will be more efficient.

         assert Iterators.combine(
             even: Iterators.iterate(0, n -> n + 2),
             odd: Iterators.iterate(1, n -> n + 2), false)
             .take(10).collect().join('\n')
             == '''
         [even:0, odd:1]
         [even:0, odd:3]
         [even:0, odd:5]
         [even:0, odd:7]
         [even:0, odd:9]
         [even:0, odd:11]
         [even:0, odd:13]
         [even:0, odd:15]
         [even:0, odd:17]
         [even:0, odd:19]
         '''.trim()

         assert Iterators.combine(
             even: Iterators.iterate(0, n -> n + 2),
             odd: Iterators.iterate(1, n -> n + 2), true)
             .take(10).collect().join('\n')
             == '''
         [even:0, odd:1]
         [even:0, odd:3]
         [even:2, odd:1]
         [even:2, odd:3]
         [even:0, odd:5]
         [even:2, odd:5]
         [even:4, odd:1]
         [even:4, odd:3]
         [even:4, odd:5]
         [even:0, odd:7]
         '''.trim()

    Parameters:
      `map` - the named source iterators
      `fairOrdering` - determine the ordering in which combinations are processed, fair implies that all source iterators will be visited roughly equally (until exhausted)
    Returns:
      the output iterator of named combinations