Като цяло няма смислова разлика между навързани извиквания и последователност от извиквания, съхраняващи средните връщащи стойности,следователно долните неща са 1 и също:
a = object.foo();
b = a.bar();
c = b.baz();
и
c = object.foo().bar().baz();
В 2-та случая, всеки метод е извикан на резултата на предното извикване. Но накрая, междинните резултати не се запазват,а се губят в следващото извикване. В случая на stream API-то,междинните резултати не трябва да бъдат използвани след като си извикал следващия метод,следователно навързването е естествения начин за ползване на стрийм като безпроблемно се грижи да не извикаш повече от 1 метод на върната референция.
Въпреки това,не е грешно да съхраняваш референции към стриймове докато се придържаш към правилото да не връщаш повече от 1 референция. Както ти си го направил в случая - презаписваш променливата с резултата на следващото извикване,като така си гарантираш да не викаш повече от 1 метод на върната референция,следователно го ползваш като хората. Разбира се, това работи само с междинни резултати на 1 и същ тип, така че когато ползваш map или flatMap, вземайки на стрийм от различен тип референция, не можеш да презапишеш локалната променлива. След това трябва да внимаваш да не използваш пак старата променлива, но както казах,докато не я ползваш след следващото извикване, няма да имаш проблеми със съхраняването на междинните стойности.
Понякога ти трябва да я запазваш,например:
try(Stream<String> stream = Files.lines(Paths.get("myFile.txt"))) {
stream.filter(s -> !s.isEmpty()).forEach(System.out::println);
}
Забележи,че кода е еквивалентен на следния:
try(Stream<String> stream = Files.lines(Paths.get("myFile.txt")).filter(s->!s.isEmpty())) {
stream.forEach(System.out::println);
}
и
try(Stream<String> srcStream = Files.lines(Paths.get("myFile.txt"))) {
Stream<String> tmp = srcStream.filter(s -> !s.isEmpty());
tmp.forEach(System.out::println);
}
Те са еднакви,понеже forEach е винаги извикан в резултат на filter-а,който винаги е извикан на резултата на Files.lines и няма значение на кой резултат последната close() операция е извикана,понеже затварянето афектира целия стрийм.
С две думи го ползваш както трябва,даже аз бих предпочел да го направя по този начин.
Не е зле да отбележим,че другите начини също биха работили без проблеми,въпреки че не са смислово еднакви:
.limit(condition? aLimit: Long.MAX_VALUE)
предполага,че максималния брой елементи, с които можеш да се сблъскаш, е Long.MAX_VALUE,
но стриймовете могат да имат дори повече елементи, може даже и да са безкрай на брой.
.limit(condition? aLimit: list.size())
Когато stream source-а е list,тотално чупи оценката на стрийма. По принцип, непостоянен стрийм сорс може произволно да бъде променен до момента,в който терминалното действие е започнало.
Резултатът ще рефклектира всички модификации направени до момента. Когато добавиш междинна операция включваща list.size(), в случая истинския размер на списъка до момента, следващите модификации, направени на колецията м/у този момент и терминалната операция, могат да накарат тази стойност да има друг смисъл вместо предназначения смисъл на „без лимит“.