private void mergeFieldIds() {
    new IdMerger<FieldId>(idsDefsOut) {
      @Override
      TableOfContents.Section getSection(TableOfContents tableOfContents) {
        return tableOfContents.fieldIds;
      }

      @Override
      FieldId read(Dex.Section in, IndexMap indexMap, int index) {
        return indexMap.adjust(in.readFieldId());
      }

      @Override
      void updateIndex(int offset, IndexMap indexMap, int oldIndex, int newIndex) {
        if (newIndex < 0 || newIndex > 0xffff) {
          throw new DexIndexOverflowException("field ID not in [0, 0xffff]: " + newIndex);
        }
        indexMap.fieldIds[oldIndex] = (short) newIndex;
      }

      @Override
      void write(FieldId value) {
        value.writeTo(idsDefsOut);
      }
    }.mergeSorted();
  }
minimum number of wasted bytes before it's worthwhile to compact the result
android/android_framework/dex-maker/src/main/java/com/android/dx/merge/DexMerger.java