Подтвердить что ты не робот

Как правильно найти характеристики потока в Java-8?

При выполнении операций с потоком во время промежуточных/pipleline-операций потоки будут создаваться с различными характеристиками (например, SORTED/SIZED/DISTINCT/ORDERED) - Освоение Lambdas (Ch 6)

Stream.of(8,3,5,6,7,4)//ORDERED, SIZED
.filer(i->i%2==0) // ORDERED
.sorted() // ORDERED, SORTED
.distinct() // DISTINCT, ORDERED, SORTED
.map(i->i+1) // ORDERED
.unordered(); //none

Как мы узнаем различные характеристики потока, как указано в приведенном выше фрагменте?

4b9b3361

Ответ 1

Я хотел бы немного расширить то, что сказали assylias (что абсолютно правильно).

Первый, эти характеристики реализованы как простое int, это двоичное представление. Сначала все нули, но когда вы добавляете определенный признак, бит устанавливается в one с помощью операции OR, удаленной с помощью операции AND.

Вы можете увидеть, где определенное свойство Spliterator устанавливает его one, просто выполняя это, например:

System.out.println(Integer.toBinaryString(Spliterator.SIZED)); // 1000000

Он устанавливает 7-й бит в один справа. Поэтому, когда вы проверяете:

Spliterator<Integer> spliterator = Stream.of(8, 3, 5, 6, 7, 4).spliterator();
System.out.println((spliterator.characteristics() & Spliterator.SIZED) == Spliterator.SIZED);

Фактически вы проверяете, установлен ли этот бит.

Второй

Есть 4 характеристики потока, которые задаются в результате создания вашего первого потока (а не двух). Либо книга немного устарела, либо вы не показали нам весь пример:

Spliterator<Integer> spliterator = Stream.of(8, 3, 5, 6, 7, 4).spliterator();

System.out.println(Integer.bitCount(spliterator.characteristics())); // 4
System.out.println(Integer.toBinaryString(spliterator.characteristics()));// 100010001010000

Эти установленные биты (равные one) соответствуют SIZED, ORDERED, IMMUTABLE, SUBSIZED.

Остальные, которые вы показали, явно неактивны - вы можете проверить их сами.

Третий

Эти характеристики чрезвычайно важны при обработке потока. Несколько примеров:

long howMany = Stream.of(1, 2, 3).map(x -> {
        System.out.println("mapping");
        return x * 2;
    }).count();
    System.out.println(howMany); // 3

В java-9 вы не увидите напечатанную mapping, потому что вы не изменили поток (вы не очистили атрибут SIZED); таким образом, не нужно даже вообще оценивать отображение.

Stream<Integer> unlimited = Stream.iterate(0, x -> x + 1); 
System.out.println(unlimited.spliterator().hasCharacteristics(Spliterator.SIZED));
Stream<Integer> limited = unlimited.limit(3);          
System.out.println(limited.spliterator().hasCharacteristics(Spliterator.SIZED));

Вы думаете, что вывод должен быть false true - мы все-таки добавляем limit, но no; результат false false: такая оптимизация не выполняется, даже если этого не мешает.

Ответ 2

На каждом этапе вы можете позвонить:

int c = stream.spliterator().characteristics();

И затем проверьте результат на константы, определенные в классе Spliterator. Например, чтобы посмотреть, упорядочен ли поток:

boolean isOrdered = (c & Spliterator.ORDERED) == Spliterator.ORDERED;

В качестве альтернативы вы можете использовать:

boolean isOrdered = stream.spliterator().hasCharacteristics(Spliterator.ORDERED);