Недавно я был удивлен тем фактом, что некоторые коллекции Java не имеют постоянной работы метода size().
В то время как я узнал, что параллельные реализации коллекций сделали некоторые компромиссы в качестве компромисса для усиления в concurrency (размер O (n) в ConcurrentLinkedQueue, ConcurrentSkipListSet, LinkedTransferQueue и т.д.), хорошая новость заключается в том, что это правильно документировано в API документация.
Меня заинтересовала производительность размера метода в представлениях, возвращаемых методами некоторых коллекций. Например, TreeSet.tailSet возвращает представление части набора поддержки, элементы которого больше или равны элементу. Меня очень удивило то, что размер звонка на возвращаемом SortedSet является линейным по времени, то есть O (n). По крайней мере, это то, что мне удалось выкопать из исходного кода OpenJDK: В TreeSet реализована как оболочка над TreeMap, а внутри TreeMap существует класс EntrySetView, метод размера которого выглядит следующим образом:
abstract class EntrySetView extends AbstractSet<Map.Entry<K,V>> {
private transient int size = -1, sizeModCount;
public int size() {
if (fromStart && toEnd)
return m.size();
if (size == -1 || sizeModCount != m.modCount) {
sizeModCount = m.modCount;
size = 0;
Iterator i = iterator();
while (i.hasNext()) {
size++;
i.next();
}
}
return size;
}
....
}
Это означает, что первый размер времени называется O (n), а затем он кэшируется до тех пор, пока резервная карта не будет изменена. Я не смог найти этот факт в документации API. Более эффективной реализацией будет O (log n) с обменом памяти при кешировании размеров поддеревьев. Поскольку такие компромиссы сделаны для избежания дублирования кода (TreeSet как оболочка над TreeMap), я не вижу причин, по которым их не следует делать по причинам производительности.
Не считая меня правильным или неправильным с моим (очень кратким) анализом реализации TreeSet OpenJDK, я хотел бы знать, есть ли подробная и полная документация о производительности многих таких операций, особенно тех, которые совершенно неожиданны?