TextRanges (@Nullable TextRange range) { if (range == null || range.isEmpty()) return this; int startIdx = Collections.binarySearch(myRanges, TextRange.from(range.getStartOffset(), 0), END_COMP); int endIdx = Collections.binarySearch(myRanges, TextRange.from(range.getEndOffset(), 0), START_COMP); if (startIdx == endIdx) { assert startIdx < 0; myRanges.add(-startIdx - 1, range); return this; } if (startIdx < 0) startIdx = -startIdx - 1; if (endIdx < 0) endIdx = -endIdx - 1; List<TextRange> covered = myRanges.subList(startIdx, endIdx); TextRange newRange = new TextRange( Math.min(range.getStartOffset(), covered.get(0).getStartOffset()), Math.max(range.getEndOffset(), covered.get(covered.size() - 1).getEndOffset()) ); covered.clear(); covered.add(newRange); return this; }