Java8 中的新特性 java.util.stream.Collectors
收集器的实现,实现各种有用的缩减操作,例如将元素累积到集合中,根据各种标准汇总元素等。
Collectors.averagingDouble()
返回一个收集器,该收集器生成应用于输入元素的双值函数的算术平均值。如果不存在任何元素,则结果为0。
由于累积的舍入误差以及不同大小的值,返回的平均值可能会根据记录值的顺序而变化。按绝对大小递增排序的值往往会产生更准确的结果。如果任何记录的值都是NaN,或者总和在任何点都是NaN,那么平均值将是NaN。
参数:mapper–提取要求和的属性的函数
例如下面代码:将整数列表转换为Double类型,并计算列表中所有数字的平均值。
class Scratch {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Double collect = list.stream().collect(Collectors.averagingDouble(number -> number));
System.out.println(collect);
}
}
输出结果为:5.5
Collectors.averagingInt()
返回一个收集器,该收集器生成应用于输入元素的整数值函数的算术平均值。如果不存在任何元素,则结果为0。
参数: mapper–提取要求和的属性的函数
Collectors.averagingInt() 方法和 Collectors.averagingDouble() 一样,不同点的是它把流中的所有元素看成是 int 类型,并返回一个浮点类型的平均值
例如下面代码:将整型列表中的所有元素转换为Double类型,并计算它们的平均值。
class Scratch {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Double collect = list.stream().collect(Collectors.averagingInt(number -> number));
System.out.println(collect);
}
}
输出结果为:5.5
Collectors.averagingLong()
返回一个收集器,该收集器生成应用于输入元素的长值函数的算术平均值。如果不存在任何元素,则结果为0。
参数: mapper–提取要求和的属性的函数
Collectors.averagingLong() 方法也和 Collectors.averagingDouble() 相似,不同点的是它把流中的所有元素看成是 long 类型,并返回一个浮点类型的平均值
例如下面代码:将给定的整数列表中的所有元素相加,并计算它们的平均值
class Scratch {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Double collect = list.stream().collect(Collectors.averagingLong(number -> number));
System.out.println(collect);
}
}
输出结果为:5.5
Collectors.collectingAndThen()
调整收集器以执行额外的精加工转换。例如,可以调整toList()收集器,使其始终生成一个不可变列表,
其中包含:
List<String>people=people.stream ().collection (collectingAndThen (toList ()Collections ::unmodifiebleList));
参数: 下游收集器修整器应用于下游收集器最终结果的函数
例如下面代码:将整数列表转换为Double类型,并计算其平方平均值。首先,将整数列表转换为流,然后使用collectingAndThen函数,先计算平均值,然后对平均值进行平方操作。
class Scratch {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Double collect = list.stream().collect(Collectors.collectingAndThen(Collectors.averagingLong(number -> number), s -> s * s));
System.out.println(collect);
}
}
输出结果为:30.25
Collectors.counting()
返回接收T类型的收集器,该收集器对输入元素的数量进行比较。如果不存在任何元素,则结果为0。
Collectors.counting() 用于统计流中元素的个数。
例如下面代码:整数列表转换为流,并使用Collectors.counting()方法计算流中元素的数量。
class Scratch {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Long collect = list.stream().collect(Collectors.counting());
System.out.println(collect);
}
}
Collectors.joining()
Collectors.joining() 方法用某个指定的拼接字符串把所有元素拼接成一个字符串,并添加可选的前缀和后缀
例如下面代码:用stream()函数将列表转换为流,并使用collect()函数将流中的元素连接为一个字符串。joining()函数用于指定元素之间的分隔符和字符串的起始和结束符。
class Scratch {
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j");
String collect= list.stream().collect(Collectors.joining(",","(",")"));
System.out.println(collect);
}
}
输出结果为:(a,b,c,d,e,f,g,h,i,j)
Collectors.maxBy() 和 Collectors.minBy()
Collectors.maxBy() 和 Collectors.minBy() 两个方法分别用于计算流中所有元素的最大值和最小值。
两个方法都可以接受一个比较器作为参数,用于如何计算最大值或最小值
例如下面代码:通过collect()方法使用Collectors.maxBy()和Collectors.minBy()分别找到列表中的最大和最小元素。
class Scratch {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(91,3,-20,35,12,213,51);
//Get Max
list.stream().collect(Collectors.maxBy(new Scratch().new IntegerComp()))
.ifPresent(i->System.out.println(i));
//Get Min
list.stream().collect(Collectors.minBy(new Scratch().new IntegerComp()))
.ifPresent(i->System.out.println(i));
}
class IntegerComp implements Comparator<Integer> {
@Override
public int compare(Integer number1, Integer number2) {
if(number1 >= number2){
return 1;
}else{
return -1;
}
}
}
}
输出结果为:213
-20
Collectors.summingInt()
返回一个收集器,该收集器生成应用应输入元素的整数数值函数的和。如果不存在任何元素,则结果为0.
例如下面代码:Collectors.summingInt() 方法将流中的所有元素视为 int 类型,并计算所有元素的总和 ( sum )
class Scratch {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int result = list.stream().collect(Collectors.summingInt(number -> number));
System.out.println(result);
}
}
输出结果为:55
Collectors.summingLong()
返回一个收集器,该收集器应用于输入元素的长值函数的和。如果不存在任何元素,则结果为0。
例如下面代码:Collectors.summingLong() 将流中的所有元素视为 long 类型,并计算所有元素的总和
class Scratch {
public static void main(String[] args) {
List<Long> list = Arrays.asList(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L);
long result = list.stream().collect(Collectors.summingLong(l->l));
System.out.println(result);
}
}
输出结果为:55
Collectors.summingDouble()
返回一个收集器,该改收集器生成应用于输入元素的双值函数的和。如果不能存在任何元素,则结果为0。
例如下面代码:Collectors.summingDouble() 将流中的所有元素视为 double 类型,并计算所有元素的总和
class Scratch {
public static void main(String[] args) {
List<Double> list = Arrays.asList(40.5,23.56,72.76);
Double result = list.stream().collect(Collectors.summingDouble(Number::doubleValue));
System.out.println(result);
}
}
输出结果为:136.82
Collectors.toList()
返回一个收集器,该收集器将所有元素积累到新的列表中,无法保证返回的List类型、可变性、可序列化性或线程安全性。
例如下面代码:Collectors.toList() 将流中的所有元素导出到一个列表 ( List ) 中
class Scratch {
public static void main(String[] args) {
List<Person> persons = Arrays.asList(new Person("John", 20), new Person("Jane", 21), new Person("Jim", 22));
List<Person> collect = persons.stream().collect(Collectors.toList());
System.out.println(collect);
}
}
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
输出结果为:[Person{name='John', age=20}, Person{name='Jane', age=21}, Person{name='Jim', age=22}]
Collectors.toSet()
返回一个收集器,该收集器将输入元素积累到一个新的集合中,不能保证返回的Set的类型、可变性、序列化性或线程安全性。
例如下面代码:Collectors.toSet() 把流中的所有元素导出到一个集合 ( Set ) 中,并排除重复的元素 ( Set 的特性 )
class Scratch {
public static void main(String[] args) {
List<Person> persons = Arrays.asList(new Person("John", 20), new Person("Jane", 21), new Person("Jim", 22));
Set<Person> collect = persons.stream().collect(Collectors.toSet());
System.out.println(collect);
}
}
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
输出结果为:[Person{name='Jim', age=22}, Person{name='John', age=20}, Person{name='Jane', age=21}]
Collectors.toMap()
返回一个收集器,该收集器将元素积累到Map中,Map的键和值是将提供的映射函数应用于输入元素的结果
例如下面代码:Collectors.toMap() 将流中的所有元素导出到一个哈希表 ( Map ) 中。该方法接受两个参数,第一个参数用于生成键 ( key ) ,第二个参数用于生成值 ( value )。两个参数都是 Lambda 表达式。
class Scratch {
public static void main(String[] args) {
List<Person> persons = Arrays.asList(new Person("John", 20), new Person("Jane", 21), new Person("Jim", 22));
Map<String, Person> collect = persons.stream().collect(Collectors.toMap(key -> key.getName(), value -> value));
System.out.println(collect);
}
}
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
输出结果为:{John=Person{name='John', age=20}, Jane=Person{name='Jane', age=21}, Jim=Person{name='Jim', age=22}}
Collectors.mapping()
通过在累加之前的将映射函数应用于每个输入元素,使接受类型U元素的收集器适用于接受类型T元素的收集
第一个参数用于 map ,第二个参数用于 reduce
例如下面代码:首先,它试图将Person对象映射到一个Map<String, Person>中,其中键是Person对象的名称,值是对应的Person对象。然后,它打印出每个年龄对应的人员名单,使用逗号分隔。
class Scratch {
public static void main(String[] args) {
List<Person> persons = Arrays.asList(new Person("John", 20),
new Person("Jane", 21),
new Person("Jim", 22),
new Person("Tom", 22));
Map<Integer, String> nameByAge = persons.stream()
.collect(Collectors.groupingBy(Person::getAge,Collectors.mapping(Person::getName, Collectors.joining(","))));
nameByAge.forEach((k,v)->System.out.println("Age:"+k +" Persons: "+v));
}
}
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
输出结果为: Age:20 Persons: John
Age:21 Persons: Jane
Age:22 Persons: Jim,Tom