请允许我提出一些抱怨,也许是令人厌烦但我想描述的是:“为什么会提出这个问题呢?”。我昨天晚上在这里、这里、这里回答的问题和其他人不一样。
consuming(stream.map(...));
consuming(stream.collect(mapping(...,toList())).stream());
void consuming(Stream<?> stream){...}
stream.collect(groupingBy(
..., mapping(
..., collectingAndThen(reducing(...), ...)
)
));
Stream operations在做一些简单的工作时比Collector更有表现力,但是它们比Collector更慢,因为它会为每个操作创建一个新的Stream,并且Stream比Collector更繁重和抽象。例如:
stream.map(...).collect(collector);
stream.collect(mapping(..., collector));
收集器无法将短路终端操作作为流应用。例如:
stream.filter(...).findFirst();
有人能想出为什么流操作与收集器重复的其他缺点/优点吗?我想重新理解它们。提前道谢。
对于那些习惯于链接方法调用的人来说,链接一个专用的终端流操作可能更具有表现力,而不是“Lisp风格”的组合收集器工厂调用。但是它也允许为流实现优化执行策略,因为它知道实际操作,而不是仅仅看到collector
抽象。
另一方面,正如您自己命名的那样,可以组合collector
s,允许在不再可能进行流操作的地方执行嵌入在另一个收集器中的这些操作。我想,这种镜像只是在Java ;8开发的后期才变得明显,这就是为什么有些操作缺少对应操作的原因,比如filtering
或flatmapping
,这些操作只有在Java ;9中才会出现。因此,让两个不同的API做类似的事情,并不是在开发开始时就做出的设计决定。
问题内容: 在深入研究之后,我发现Stream和Collector之间存在许多重复的逻辑,这些逻辑违反了不要重复自己的原则,例如:jdk-9和中的Stream#map&Collectors#mapping,Stream#filter&Collectors#filtering。等等 但自从溪流遵守告诉,不要问得墨meter耳的法则/ 得墨Law律和集热器遵守继承构成原则看来,这是合理的。 我只能想到
我正在为新手程序员编写一个库,所以我试图保持API尽可能干净。 我的库需要做的事情之一是对大量的ints或long集合执行一些复杂的计算。我的用户需要从许多场景和业务对象中计算这些值,因此我认为最好的方法是使用流来允许用户将业务对象映射到或,然后在收集器中计算这些计算。 所以与其能够做到 我必须提供这样的供应商、累加器和组合器: 这对我的新手用户来说太复杂了,而且很容易出错。 在使用或的同时,是否
以下是MWE: 奇怪的是,无论我键入
AFAIK对流求和的唯一方法是: 这里的问题是,每次调用都会创建一个新的,而不是更改可变类型。 对于
我试图理解是什么保存了对对象的引用,使得它们在执行Java流终端操作时不符合垃圾收集的条件? 这是我的测试代码 从未调用LargetObject的finalize方法。 我的想法是一旦. map(largeObject- 为什么这不会发生?也许真的可以做些什么?
问题内容: 是什么决定了垃圾收集器何时真正收集?它是在一定时间之后还是在一定数量的内存用完之后发生的吗?还是还有其他因素? 问题答案: 它在确定是时候运行时运行。在世代垃圾收集器中,一种常见的策略是在第0代内存分配失败时运行收集器。也就是说,每次你分配一小块内存(大块通常直接放置在“旧”代中)时,系统都会检查gen-0堆中是否有足够的可用空间,如果没有,则运行GC释放空间以使分配成功。然后将旧数据