Разве не гарантируется, что параллельный поток, полученный из списка, всегда будет вести себя как его последовательный аналог и давать одинаковый, предсказуемый результат? - PullRequest
6 голосов
/ 09 июня 2019

Следующий код печатает true для 100 раз:

for(int i=0; i<100; i++) {
   String s2 = Arrays.asList("A", "E", "I", "O", "U").parallelStream().reduce("x", String::concat, String::concat);
   System.out.println("xAxExIxOxU".equals(s2));
}

Конечно, 100 раз не является гарантией. Но разве не кажется, что даже если используемая здесь идентичность не соответствует требованию "... для всех u, combiner.apply (identity, u) равно u" для doc , мы все еще можем сказать, что параллельный поток, полученный из списка или любой другой по своей природе упорядоченной структуры, будет вести себя так же, как последовательный поток в redu (), возвращая тот же результат?

1 Ответ

4 голосов
/ 09 июня 2019

Javadoc для функции Stream.reduce с аргументом идентификации говорит:

Значение идентификации должно быть идентификатором для функции аккумулятора.Это означает, что для всех t, аккумулятора.apply (identity, t) равно t.

Что явно не так - "x".concat(anything) не равно anything.Единственное действительное значение идентификатора здесь - "".

Если вы проверили предпосылку заголовка вашего вопроса - увидев, что возвращает непараллельная операция - вы увидитечто ответ на ваш заголовок - «нет» - потому что непараллельный поток возвращает "xAEIOU" для вашей операции сокращения.

Если вы измените значение идентификатора с "x" на "", тогда ответбыло бы «да, такая гарантия есть, так как ваша функция приведения является ассоциативной и ограничения на значение идентификатора также выполняются».

Даже с вашим измененным заголовком ответ таков:clear:

Вы нарушаете контракт функции reduce, предоставляя в качестве значения идентификатора значение, которое не является значением идентификатора для вашей функции Reduce.Таким образом, поскольку вы нарушаете контракт методов reduce, все гарантии отключены.

Легко создать случай, когда он не выполняется;просто увеличьте свой список, как уже отмечал Хольгер:

List<String> list = new ArrayList<>();
for (int i = 0; i < 500; i++) {
    list.add("A");
}
String s2 = list.parallelStream().reduce("x", String::concat, String::concat);
System.out.println(s2);
if (s2.length() != list.size() * 2) {
    System.out.println("Bad s2 size");
}
...