@Override
  public <T extends ExternalizableGraphElement> void writeGraphElementCollection(Class<? extends T> elemType, @NotNull Iterable<T> col) throws IOException {
    writeUTF(elemType.getName());
    if (FactoredExternalizableGraphElement.class.isAssignableFrom(elemType)) {
      Map<ExternalizableGraphElement, List<FactoredExternalizableGraphElement<?>>> elemGroups = new HashMap<>();
      for (T e : col) {
        FactoredExternalizableGraphElement<?> fe = (FactoredExternalizableGraphElement<?>)e;
        elemGroups.computeIfAbsent(fe.getFactorData(), k -> new SmartList<>()).add(fe);
      }
      writeInt(elemGroups.size());
      for (Map.Entry<ExternalizableGraphElement, List<FactoredExternalizableGraphElement<?>>> entry : elemGroups.entrySet()) {
        RW.writeCollection(this, entry.getValue(), new RW.Writer<>() {
          private boolean commonPartWritten;
          @Override
          public void write(FactoredExternalizableGraphElement<?> elem) throws IOException {
            if (!commonPartWritten) {
              commonPartWritten = true;
              writeGraphElement(entry.getKey());
            }
            elem.write(GraphDataOutputImpl.this);
          }
        });
      }
    }
    else {
      RW.writeCollection(this, col, elem -> elem.write(this));
    }
  }
@Override
  public <T extends ExternalizableGraphElement> void writeGraphElementCollection(Class<? extends T> elemType, @NotNull Iterable<T> col)