code: public String collapseFrom(CharSequence sequence, char replacement) {
      // This implementation avoids unnecessary allocation.
      int len = sequence.length();
      for (int i = 0; i < len; i++) {
        char c = sequence.charAt(i);
        if (matches(c)) {
          if (c == replacement
              && (i == len - 1 || !matches(sequence.charAt(i + 1)))) {
            // a no-op replacement
            i++;
          } else {
            StringBuilder builder = new StringBuilder(len)
                .append(sequence.subSequence(0, i))
                .append(replacement);
            return finishCollapseFrom(sequence, i + 1, len, replacement, builder, true);
          }
        }
      }
      // no replacement needed
      return sequence.toString();
    }
docs: Returns a string copy of the input character sequence, with each group of consecutive
  characters that match this matcher replaced by a single replacement character. For example:
  <pre>   {@code
  
  CharMatcher.anyOf("eko").collapseFrom("bookkeeper", '-')}</pre>
  
  ... returns {@code "b-p-r"}.
  
  <p>The default implementation uses {@link #indexIn(CharSequence)} to find the first matching
  character, then iterates the remainder of the sequence calling {@link #matches(char)} for each
  character.
  
  @param sequence the character sequence to replace matching groups of characters in
  @param replacement the character to append to the result string in place of each group of
  matching characters in {@code sequence}
  @return the new string