Mad*_*han 5 java arraylist java-8 java-stream
我有一个结果列表。我需要找到通过的结果计数。但列表中的某些项目之间存在关系。例如。我有这样的清单
1.0 - false
2.0 - true
3.0 - false
4.0 - true
1.1 - true
3.1 - true
Run Code Online (Sandbox Code Playgroud)
那么通过的计数应该是 2 而不是 4。因为我想根据 id 对列表进行分组(1,1.2,1.3,1.xx 到单个组中),如果组中的所有项目都是,则将其标记为通过经过 。我尝试过小组使用groupingBy,并且得到了我预期行为的地图。我可以迭代地图并获取计数。但我想知道有什么方法可以简单地使用 Java 8 来做到这一点。
public class Main {
static class Resultx {
double id = 1;
Boolean passed = false;
public void setId(double id) {
this.id = id;
}
public double getId() {
return id;
}
public void setAsPassed() {
this.passed = true;
}
public Boolean getPassed() {
return passed;
}
@Override
public String toString() {
return getId() + " - " + getPassed();
}
}
public static void main(String[] args) {
List<Resultx> results = new ArrayList<>();
for (int i = 1; i < 5; i++) {
Resultx result = new Resultx();
result.setId(i);
if (i % 2 == 0) {
result.setAsPassed();
}
results.add(result);
}
for (int i = 1; i < 5; i += 2) {
Resultx result = new Resultx();
result.setId(i + .1);
result.setAsPassed();
results.add(result);
}
System.out.println(results.size());
results.forEach(System.out::println);
System.out.println(results.stream().filter(Resultx::getPassed).count());
System.out.println(results.stream().filter(e -> !e.getPassed()).count());
System.out.println(results.stream().collect(Collectors.groupingBy(r -> (int) (r.getId()))));
}
}
Run Code Online (Sandbox Code Playgroud)
输出
Total count - 6
1.0 - false
2.0 - true
3.0 - false
4.0 - true
1.1 - true
3.1 - true
Total pass count - 4
Total fail count - 2
{1=[1.0 - false, 1.1 - true], 2=[2.0 - true], 3=[3.0 - false, 3.1 - true], 4=[4.0 - true]}
Run Code Online (Sandbox Code Playgroud)
我想要总体通过计数和总体失败计数。这是 2 和 2
试试这个
Map<Boolean, Long> collect = results.stream()
.collect(Collectors.groupingBy(r -> (int) (r.getId()))).values()
.stream().map(l -> l.stream().allMatch(p -> p.getPassed()))
.collect(Collectors.partitioningBy(k -> k, Collectors.counting()));
System.out.println(collect);
Run Code Online (Sandbox Code Playgroud)
哪个显示:
{false=2, true=2}
Run Code Online (Sandbox Code Playgroud)
您的代码有一些奇怪的事情,例如使用ID,您只是在分组操作中将double其转换为 ID ,或者使用for you属性而不是仅使用. 使用引用类型,打开了成为 的机会,如果打算这种可能性,您将必须处理它。否则,只需使用.intBooleanpassedbooleanBooleannullboolean
它\xe2\x80\x99s也不清楚,你真正想要什么结果。这个例子不足以描述它。
\n\n如果您只想计算组数,其中truemeans \xe2\x80\x9call where true\xe2\x80\x9d 和falsemeans \xe2\x80\x9csome where false\xe2\x80\x9d,你可以这样做简单
Map<Boolean,Long> counts = results.stream()\n .collect(Collectors.collectingAndThen(\n Collectors.toMap(r -> (int)r.getId(), Resultx::getPassed, Boolean::logicalAnd),\n m -> m.values().stream()\n .collect(Collectors.partitioningBy(b -> b, Collectors.counting()))\n ));\nRun Code Online (Sandbox Code Playgroud)\n\n如果你想计算组中的元素,事情就会变得更加复杂。
\n\nint totalPassedCount = results.stream()\n .collect(Collectors.collectingAndThen(Collectors.groupingBy(r -> (int)r.getId(),\n Collector.of(() -> new Object() { int count = 0; boolean pass = true; },\n (o, r) -> { o.count++; o.pass &= r.getPassed(); },\n (x, y) -> { x.count += y.count; x.pass &= y.pass; return x; },\n o -> o.pass? o.count: 0\n )),\n (Map<Integer,Integer> x) -> x.values().stream().mapToInt(i -> i).sum()\n ));\nSystem.out.println(totalPassedCount);\nRun Code Online (Sandbox Code Playgroud)\n\n这使用自定义收集器作为 的下游收集器groupingBy。此自定义收集器收集到一个对象中,该对象保存元素计数以及是否所有元素都通过了,然后,在完成步骤中,如果组中的所有元素都通过了,则用计数替换这些对象,否则为零。然后,向收集器添加一个整理步骤,groupingBy该步骤将汇总所有这些值。
上面的解决方案是为了获取通过的计数,正如您在问题开头所要求的那样。由于您\xe2\x80\x99最后要求两者,您可以使用
\n\nMap<Boolean,Integer> counts = results.stream()\n .collect(Collectors.collectingAndThen(Collectors.groupingBy(r -> (int)r.getId(),\n Collector.of(() -> new Object() { int count = 0; boolean pass = true; },\n (o, r) -> { o.count++; o.pass &= r.getPassed(); },\n (x, y) -> { x.count += y.count; x.pass &= y.pass; return x; }\n )),\n m -> m.values().stream().collect(\n Collectors.partitioningBy(o -> o.pass, Collectors.summingInt(o -> o.count)))\n ));\nRun Code Online (Sandbox Code Playgroud)\n\n为了两者兼得。
\n\n或者,因为从单个示例中获取预期规则很困难,
\n\nMap<Boolean,Integer> counts = results.stream()\n .collect(Collectors.collectingAndThen(Collectors.groupingBy(r -> (int)r.getId(),\n Collector.of(() -> new Object() { int passed, failed; },\n (o, r) -> { if(r.getPassed()) o.passed++; else o.failed++; },\n (x, y) -> { x.passed += y.passed; x.failed += y.failed; return x; }\n )),\n m -> m.values().stream()\n .filter(o -> o.passed == 0 || o.failed == 0)\n .collect(Collectors.partitioningBy(o -> o.failed==0,\n Collectors.summingInt(o -> o.failed==0? o.passed: o.failed)))\n ));\nRun Code Online (Sandbox Code Playgroud)\n\n如果组中的所有元素都通过或失败,则仅计算passed和。failed但既然你说过,你\xe2\x80\x99d期望2和2,你可以删除该.filter(o -> o.passed == 0 || o.failed == 0)行。passed然后,仅当组中的所有元素都通过时才会进行计数,但failed即使组中的某些元素通过了,也会对 all 进行计数。然后,你\xe2\x80\x99d得到2结果2。
| 归档时间: |
|
| 查看次数: |
7167 次 |
| 最近记录: |