code: public <A, D> Map<K, D> grouping(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)) {
              return collect(Collectors.groupingByConcurrent(keyMapper, mapping));
          }
          return collect(Collectors.groupingBy(keyMapper, 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.
  
  <p>
  There are no guarantees on the type, mutability, serializability, or
  thread-safety of the {@code Map} object returned. If more control over
  the returned {@code Map} is required, use
  {@link #grouping(Supplier, Collector)}.
  
  <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 downstream a {@code Collector} implementing the downstream
  reduction
  @return a {@code Map} containing the elements of this stream
  @see Collectors#groupingBy(Function, Collector)