code: public static <T,E> Collection<T> collectMany(Iterable<E> self, Collection<T> collector, @ClosureParams(FirstParam.FirstGenericType.class) Closure<Collection<? extends T>> projection) {
          for (E next : self) {
              collector.addAll(projection.call(next));
          }
          return collector;
      }
docs: Projects each item from a source collection to a result collection and concatenates (flattens) the resulting
  collections adding them into the <code>collector</code>.
  <p>
  <pre class="groovyTestCase">
  def animals = ['CAT', 'DOG', 'ELEPHANT'] as Set
  def smallAnimals = animals.collectMany(['ant', 'bee']){ it.size() {@code >} 3 ? [] : [it.toLowerCase()] }
  assert smallAnimals == ['ant', 'bee', 'cat', 'dog']
  
  def nums = 1..5
  def origPlusIncrements = nums.collectMany([] as Set){ [it, it+1] }
  assert origPlusIncrements.size() == nums.size() + 1
  </pre>
  
  @param self       an Iterable
  @param collector  an initial collection to add the projected items to
  @param projection a projecting Closure returning a collection of items
  @return the collector with the projected collections concatenated (flattened) into it
  @since 2.2.0