Ответ 1
Работает ли он в постоянном или линейном времени?
Текущая реализация выполняется в линейном времени:
public final long count() {
return mapToLong(e -> 1L).sum();
}
Но это может быть улучшено (там RFE для этого где-то), чтобы работать в постоянное время в некоторых ситуациях.
Как? Поток описывается источником потока, нулевыми или более промежуточными операциями и терминальной операцией (здесь count()
- операция терминала). Реализация потока поддерживает набор характеристик об источнике и знает, как характеристики изменяются операциями. Например, поток, поддерживаемый коллекцией, имеет характеристику SIZED
, тогда как поток, поддерживаемый Iterator, не имеет размера. Точно так же операция map()
сохраняется в размере, но операция filter()
уничтожает любые априорные знания о размерах. Реализация потока знает составные характеристики конвейера, прежде чем он запустит операцию терминала, поэтому он знает, зависит ли исходный размер и все ли размеры сохраняются по размеру, и в таких случаях может просто задать источник для размера и обойти все фактическое вычисление потока. (Но реализация на Java 8 не выполняется).
Обратите внимание, что потоки не должны быть специализированными для поддержки этого; классы Collection создают поток с Spliterator
, который знает его характеристики, поэтому специализированная реализация для Collections не нужна, просто обновляя общую реализацию, чтобы использовать этот конкретный бит информации.