我有
List
的员工,他们的特点是工资。
为什么这段代码不起作用?
String joined = employees.stream().collect(
Collectors.summingInt(Employee::getSalary),
Collectors.maxBy(Comparator.comparing(Employee::getSalary)),
Collectors.minBy(Comparator.comparing(Employee::getSalary)),
Collectors.averagingLong((Employee e) ->e.getSalary() * 2),
Collectors.counting(),
Collectors.joining(", "));
我正在使用一套收集器。
请注意,当前您试图获取的不是最高/最低工资,而是具有此类工资的员工。如果您实际上想要拥有最高/最低工资本身(数字),那么可以使用
Collectors.summarizingInt()
: 立即计算这些特征
IntSummaryStatistics stats = employees.stream()
.collect(Collectors.summarizingInt(Employee::getSalary));
如果你想将它们连接成字符串,你可以使用:
String statsString = Stream.of(stats.getSum(), stats.getMax(), stats.getMin(),
stats.getAverage()*2, stats.getCount())
.map(Object::toString)
.collect(Collectors.joining(", "));
如果您确实想获得最高/最低工资的员工,这里
IntSummaryStatistics
不会帮助您。但是,您可以创建收集器流:
String result = Stream.<Collector<Employee,?,?>>of(
Collectors.summingInt(Employee::getSalary),
Collectors.maxBy(Comparator.comparing(Employee::getSalary)),
Collectors.minBy(Comparator.comparing(Employee::getSalary)),
Collectors.averagingLong((Employee e) ->e.getSalary() * 2),
Collectors.counting())
.map(collector -> employees.stream().collect(collector))
.map(Object::toString)
.collect(Collectors.joining(", "));
请注意,通过这种方式,您将得到类似的输出(取决于
Employee.toString()
实现:
1121, Optional[Employee [salary=1000]], Optional[Employee [salary=1]], 560.5, 4
不要忘记
maxBy
/minBy
返回Optional
。
如果您对第一个解决方案不满意,并且由于某种原因不想多次迭代输入,您可以使用如下方法创建组合收集器:
/**
* Returns a collector which joins the results of supplied collectors
* into the single string using the supplied delimiter.
*/
@SafeVarargs
public static <T> Collector<T, ?, String> joining(CharSequence delimiter,
Collector<T, ?, ?>... collectors) {
@SuppressWarnings("unchecked")
Collector<T, Object, Object>[] cs = (Collector<T, Object, Object>[]) collectors;
return Collector.<T, Object[], String>of(
() -> Stream.of(cs).map(c -> c.supplier().get()).toArray(),
(acc, t) -> IntStream.range(0, acc.length)
.forEach(idx -> cs[idx].accumulator().accept(acc[idx], t)),
(acc1, acc2) -> IntStream.range(0, acc1.length)
.mapToObj(idx -> cs[idx].combiner().apply(acc1[idx], acc2[idx]))
.toArray(),
acc -> IntStream.range(0, acc.length)
.mapToObj(idx -> cs[idx].finisher().apply(acc[idx]).toString())
.collect(Collectors.joining(delimiter)));
}
有了这样的方法就可以写了
String stats = employees.stream().collect(joining(", ",
Collectors.summingInt(Employee::getSalary),
Collectors.maxBy(Comparator.comparing(Employee::getSalary)),
Collectors.minBy(Comparator.comparing(Employee::getSalary)),
Collectors.averagingLong((Employee e) ->e.getSalary() * 2),
Collectors.counting()));
我终于找到了解决方案..感谢你们的尝试
String s = employees.stream().mapToDouble(a>a.getSalary()).summaryStatistics().toString();
这是输出:
DoubleSummaryStatistics{count=21, sum=17200,000000, min=100,000000,
average=819,047619, max=2100,000000}
如果我们只想查找所有工资的总和,可以使用以下解决方案。
Integer a= emp.stream().collect(Collectors.summingInt(Employe::getSalary));