code: @SuppressWarnings("unchecked")
      public <A, D, M extends Map<K, D>> M grouping(Supplier<M> mapSupplier, Collector<? super V, A, D> downstream) {
          Function<Entry<K, V>, K> keyMapper = Entry::getKey;
          Collector<Entry<K, V>, ?, D> mapping = Collectors.mapping(Entry::getValue, downstream);
          if (isParallel() && downstream.characteristics().contains(Characteristics.UNORDERED)
              && mapSupplier.get() instanceof ConcurrentMap) {
              return (M) collect(Collectors.groupingByConcurrent(keyMapper,
                  (Supplier<? extends ConcurrentMap<K, D>>) mapSupplier, mapping));
          }
          return collect(Collectors.groupingBy(keyMapper, mapSupplier, mapping));
      }
docs: Returns a {@link Map} where elements of this stream with the same key are
  grouped together. The resulting {@code Map} keys are the keys of this
  stream entries and the corresponding values are combined using the
  provided downstream collector. The {@code Map} is created using
  the provided supplier function.
  
  <p>
  This is a <a href="package-summary.html#StreamOps">terminal</a>
  operation.
  
  @param <A> the intermediate accumulation type of the downstream collector
  @param <D> the result type of the downstream reduction
  @param <M> the type of the resulting {@code Map}
  @param mapSupplier a function which returns a new, empty {@code Map} into
  which the results will be inserted
  @param downstream a {@code Collector} implementing the downstream
  reduction
  @return a {@code Map} containing the elements of this stream
  @see Collectors#groupingBy(Function, Supplier, Collector)