域名申请通过了网站怎么做,网站域名注册流程,快速装修公司,网站如何发布到网上Accumulative是针对CollectorT, A, R的中间累积类型A提出的接口CollectorT, A, R以使定义自定义Java Collector更加容易。 介绍 如果您曾经使用过Java Stream #xff0c;那么很可能使用了一些Collector #xff0c;例如#xff1a; Collectors.toList C… Accumulative是针对CollectorT, A, R的中间累积类型A提出的接口CollectorT, A, R以使定义自定义Java Collector更加容易。 介绍 如果您曾经使用过Java Stream 那么很可能使用了一些Collector 例如 Collectors.toList Collectors.toMap 但是你有没有使用过…… 组成的 Collector 它使用另一个 Collector作为参数例如 Collectors.collectingAndThen 。 定制 Collector 其功能在Collector.of明确指定。 这篇文章是关于custom Collector的。 集电极 让我们回想一下Collector合同的本质 我的评论 /** * param T (input) element type * param A (intermediate) mutable accumulation type (container) * param R (output) result type */ public interface CollectorT, A, R { SupplierA supplier(); // create a container BiConsumerA, T accumulator(); // add to the container BinaryOperatorA combiner(); // combine two containers FunctionA, R finisher(); // get the final result from the container SetCharacteristics characteristics(); // irrelevant here } 上面的合同本质上是功能性的这非常好 这使我们可以使用任意累积类型 A 创建Collector 例如 A StringBuilder Collectors.joining A OptionalBox Collectors.reducing A long[] Collectors.averagingLong 提案 在我提供任何理由之前我将提出建议因为它很简短。 该提议的完整源代码可以在GitHub上找到 。 累积接口 我建议将以下称为Accumulative 名称待讨论的接口添加到JDK public interface AccumulativeT, A extends AccumulativeT, A, R, R { void accumulate(T t); // target for Collector.accumulator() A combine(A other); // target for Collector.combiner() R finish(); // target for Collector.finisher() } 与Collector相反此接口本质上是面向对象的 实现该接口的类必须表示某种可变状态 。 过载收集器 具有Accumulative 我们可以添加以下Collector.of重载 public static T, A extends AccumulativeT, A, R, R CollectorT, ?, R of( SupplierA supplier, Collector.Characteristics... characteristics) { return Collector.of(supplier, A::accumulate, A::combine, A::finish, characteristics); } 普通开发者故事 在本部分中我将展示该建议会对普通开发人员产生怎样的影响而一般开发人员仅了解 Collector API的基础知识 。 如果您精通此API请在继续阅读之前尽力想象您不知道。 例 让我们重用我最近的文章中的示例进一步简化。 假设我们有一个Stream interface IssueWiseText { int issueLength(); int textLength(); } 并且我们需要计算问题覆盖率 总发行时长 ───────────── 总文字长度 此要求转换为以下签名 CollectorIssueWiseText, ?, Double toIssueCoverage(); 解 一般的开发人员可能会决定使用自定义累积类型A来解决此问题不过其他解决方案也是可能的 。 假设开发人员将其命名为CoverageContainer这样 T IssueWiseText A CoverageContainer R Double 在下面我将展示这样的开发人员如何实现CoverageContainer的结构 。 无累积结构 注意 本节很长目的是说明该过程对于没有使用Collector的开发人员可能有多复杂 。 如果您已经意识到这一点则可以跳过它 如果没有Accumulative 则开发人员将查看Collector.of 并看到四个主要参数 SupplierA supplier BiConsumerA, T accumulator BinaryOperatorA combiner FunctionA, R finisher 要处理Supplier A supplier 开发人员应 在SupplierA中用心理替代A获得SupplierCoverageContainer 在精神上将签名解析为CoverageContainer get () 回想一下JavaDoc for Collector.supplier() 第四种调用方法的引用 对构造函数的引用 意识到supplier CoverageContainer::new 要处理BiConsumer A, T accumulator 开发人员应 BiConsumerCoverageContainer, IssueWiseText void accept (CoverageContainer a, IssueWiseText t) 在精神上将签名转换为一种实例方法 void accumulate(IssueWiseText t) 第三种调用方法的引用 引用特定类型的任意对象的实例方法 意识到accumulator CoverageContainer::accumulate 处理BinaryOperator A combiner BinaryOperatorCoverageContainer CoverageContainer apply (CoverageContainer a, CoverageContainer b) CoverageContainer combine(CoverageContainer other) combiner CoverageContainer::combine 要处理Function A, R finisher FunctionCoverageContainer, Double Double apply (CoverageContainer a) double issueCoverage() finisher CoverageContainer::issueCoverage 这个漫长的过程导致 class CoverageContainer { void accumulate(IssueWiseText t) { } CoverageContainer combine(CoverageContainer other) { } double issueCoverage() { } } 开发人员可以定义toIssueCoverage() 必须以正确的顺序提供参数 CollectorIssueWiseText, ?, Double toIssueCoverage() { return Collector.of( CoverageContainer:: new , CoverageContainer::accumulate, CoverageContainer::combine, CoverageContainer::finish ); } 累积结构 现在 使用 Accumulative 开发人员将查看新的Collector.of重载并且将仅看到一个主要参数 SupplierA supplier 和一个有界类型参数 A extends AccumulativeT, A, R 因此开发人员将自然而然地开始- 实施 AccumulativeT, A, R并第一次和最后一次解析T A和R class CoverageContainer implements AccumulativeIssueWiseText, CoverageContainer, Double { } 此时一个不错的IDE会抱怨该类必须实现所有抽象方法。 而且这是最美丽的部分 它将提供快速修复。 在IntelliJ中您单击“ Alt Enter”→“实施方法”然后…就完成了 class CoverageContainer implements AccumulativeIssueWiseText, CoverageContainer, Double { Override public void accumulate(IssueWiseText issueWiseText) { } Override public CoverageContainer combine(CoverageContainer other) { return null ; } Override public Double finish() { return null ; } } 因此您不必摆弄类型手动编写任何内容或命名任何内容 哦是的-您仍然需要定义toIssueCoverage() 但是现在很简单 CollectorIssueWiseText, ?, Double toIssueCoverage() { return Collector.of(CoverageContainer:: new ); } 那不是很好吗 实作 这里的实现无关紧要因为这两种情况 diff 几乎相同。 基本原理 程序太复杂 我希望我已经演示了如何定义自定义Collector是一个挑战。 我必须说即使我总是不愿意定义一个。 但是我也感觉到-有了Accumulative 这种勉强就会消失因为该过程将缩小为两个步骤 实现AccumulativeT, A, R 调用Collector.of(YourContainer::new) 推动实施 JetBrains创造了“ 发展动力 ”我想将其转变为“实施动力”。 由于Collector是一个简单的功能的设备中这通常是没有意义的据我可以告诉来实现它也有例外 。 但是通过Google搜索“实施收集器”可以看到约5000个结果人们正在这样做。 这很自然因为要在Java中创建“自定义” TYPE 通常会扩展/实现TYPE 。 实际上即使是经验丰富的开发人员例如Java冠军Tomasz Nurkiewicz 也可以做到这一点。 总结起来人们感到有实现的动力 但在这种情况下JDK没有为他们提供实现的任何东西。 Accumulative可以填补这一空白…… 相关例子 最后我搜索了一些示例这些示例可以轻松实现Accumulative 。 在OpenJDK尽管这不是目标位置中我发现了两个 Collectors.reducing diff Collectors.teeing diff 对堆栈溢出虽然我发现大量的 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 。 我还发现了一些基于数组的示例可以将其重构为Accumulative以获得更好的可读性 a b c 。 命名 Accumulative不是最好的名字主要是因为它是一个形容词 。 但是我选择它是因为 我希望名称以A开头如T, A, R 我最好的候选人 Accumulator 已经被BiConsumerA, T accumulator() AccumulativeContainer似乎太长。 在OpenJDK中 A称为 可变结果容器 累积类型 容器 州 框 提示以下替代方法 AccumulatingBox AccumulationState Collector.Container MutableResultContainer 当然如果这个想法被接受这个名字将通过“传统”的名字 摘要 在本文中我建议向JDK添加Accumulative接口和新的Collector.of重载。 有了它们开发人员将不再费劲地创建自定义Collector 。 取而代之的是它只是成为“执行合同”和“引用构造函数”。 换句话说该提案旨在降低进入“定制Collector世界的门槛 附录 下面的可选阅读。 解决方案示例JDK 12 在JDK 12中由于Collectors.teeing JDK-8209685 我们将toIssueCoverage()定义为组合的Collector 。 static CollectorIssueWiseText, ?, Double toIssueCoverage() {return Collectors.teeing(Collectors.summingInt(IssueWiseText::issueLength),Collectors.summingInt(IssueWiseText::textLength),(totalIssueLength, totalTextLength) - (double) totalIssueLength / totalTextLength);
} 上面的内容很简洁但是对于Collector API新手来说可能很难遵循。 示例解决方案JDK方法 另外 toIssueCoverage()可以定义为 static CollectorIssueWiseText, ?, Double toIssueCoverage() {return Collector.of(() - new int[2],(a, t) - { a[0] t.issueLength(); a[1] t.textLength(); },(a, b) - { a[0] b[0]; a[1] b[1]; return a; },a - (double) a[0] / a[1]);
} 我称其为“ JDK方式”因为某些Collector的实现与OpenJDK中的实现类似例如Collector.averagingInt 。 但是尽管这样的简洁代码可能适用于OpenJDK但由于可读性高这很低我称之为cryptic 因此它肯定不适合业务逻辑。 翻译自: https://www.javacodegeeks.com/2019/02/accumulative-custom-java-collectors.html