code: public static <T> Iterator<List<T>> groupBy(final Iterator<? extends T> iterator, final Function<? super T, ?> groupingFunction) {
          requireNonNull(iterator);
          requireNonNull(groupingFunction);
          return new AbstractIterator<List<T>>() {
              private final PeekingIterator<T> peekingIterator = peekingIterator(iterator);
  
              @Override
              protected List<T> computeNext() {
                  if (!peekingIterator.hasNext())
                      return endOfData();
  
                  Object key = groupingFunction.apply(peekingIterator.peek());
                  List<T> group = new ArrayList<>();
  
                  do {
                      group.add(peekingIterator.next());
                  } while (peekingIterator.hasNext() && Objects.equals(key, groupingFunction.apply(peekingIterator.peek())));
  
                  return unmodifiableList(group);
              }
          };
      }
docs: Divides an iterator into unmodifiable sublists of equivalent elements. The iterator groups elements
  in consecutive order, forming a new parition when the value from the provided function changes. For example,
  grouping the iterator {@code [1, 3, 2, 4, 5]} with a function grouping even and odd numbers
  yields {@code [[1, 3], [2, 4], [5]} all in the original order.
  
  <p/>
  <p>The returned lists implement {@link java.util.RandomAccess}.