code: public Tags merge(Tags other) {
      // Dereference "other" first as a null pointer check so we cannot risk returning null later.
      if (other.isEmpty()) {
        return this;
      }
      if (this.isEmpty()) {
        return other;
      }
      SortedMap<String, SortedSet<Object>> merged = new TreeMap<String, SortedSet<Object>>();
      for (Map.Entry<String, SortedSet<Object>> e : map.entrySet()) {
        SortedSet<Object> otherValues = other.map.get(e.getKey());
        if (otherValues == null || e.getValue().containsAll(otherValues)) {
          // Our values are a superset of the values in the other map, so just use them.
          merged.put(e.getKey(), e.getValue());
        } else if (otherValues.containsAll(e.getValue())) {
          // The other map's values are a superset of ours, so just use them.
          merged.put(e.getKey(), otherValues);
        } else {
          // Values exist in both maps and neither is a superset, so we really must merge.
          SortedSet<Object> mergedValues = new TreeSet<Object>(e.getValue());
          mergedValues.addAll(otherValues);
          merged.put(e.getKey(), Collections.unmodifiableSortedSet(mergedValues));
        }
      }
      for (Map.Entry<String, SortedSet<Object>> e : other.map.entrySet()) {
        // Finally add those values that were only in the other map.
        if (!map.containsKey(e.getKey())) {
          merged.put(e.getKey(), e.getValue());
        }
      }
      return new Tags(Collections.unmodifiableSortedMap(merged));
    }
docs: Merges two tags instances, combining values for any name contained in both.