JDK1.8工作中常用的Collectors类聚合方法

一:简介

Stream中有两个个方法collect和collectingAndThen用于对流中的数据进行处理,可以对流中的数据进行聚合操作,如:

  • 将流中的数据转成集合类型: toList、toSet、toMap、toCollection
  • 将流中的数据(字符串)使用分隔符拼接在一起:joining
  • 对流中的数据求最大值maxBy、最小值minBy、求和summingInt、求平均值averagingDouble
  • 对流中的数据进行映射处理 mapping
  • 对流中的数据分组:groupingBy、partitioningBy
  • 对流中的数据累计计算:reducing


纯干货 | JDK1.8工作中常用的Collectors类聚合方法

<code>public final class Collectors {

// 转换成集合
public static Collector> toList();
public static Collector> toSet();
public static Collector> toMap(Function super T, ? extends K> keyMapper,
Function super T, ? extends U> valueMapper);
public static > Collector toCollection(Supplier collectionFactory);

// 拼接字符串,有多个重载方法
public static Collector<charsequence> joining(CharSequence delimiter);
public static Collector<charsequence> joining(CharSequence delimiter,
CharSequence prefix,
CharSequence suffix);
// 最大值、最小值、求和、平均值
public static Collector> maxBy(Comparator super T> comparator);
public static Collector> minBy(Comparator super T> comparator);
public static Collector summingInt(ToIntFunction super T> mapper);
public static Collector averagingDouble(ToDoubleFunction super T> mapper);

// 分组:可以分成true和false两组,也可以根据字段分成多组
public static Collector>> groupingBy(Function super T, ? extends K> classifier);
// 只能分成true和false两组

public static Collector>> partitioningBy(Predicate super T> predicate);

// 映射
public static Collector mapping(Function super T, ? extends U> mapper,
Collector super U, A, R> downstream);

public static Collector reducing(U identity,
Function super T, ? extends U> mapper,
BinaryOperator op);
}
/<charsequence>/<charsequence>
/<code>

二:示例

流转换成集合

<code>@Test
public void testToCollection(){
List<integer> list = Arrays.asList(1, 2, 3);

// [10, 20, 30]
List<integer> collect = list.stream().map(i -> i * 10).collect(Collectors.toList());

// [20, 10, 30]
Set<integer> collect1 = list.stream().map(i -> i * 10).collect(Collectors.toSet());

// {key1=value:10, key2=value:20, key3=value:30}
Map<string> collect2 = list.stream().map(i -> i * 10).collect(Collectors.toMap(key -> "key" + key/10, value -> "value:" + value));

// [1, 3, 4]
TreeSet<integer> collect3= Stream.of(1, 3, 4).collect(Collectors.toCollection(TreeSet::new));
}
/<integer>/<string>/<integer>/<integer>/<integer>/<code>
<code>@Data
@ToString
@AllArgsConstructor
@RequiredArgsConstructor
public class User {
private Long id;
private String username;
}

@Test
public void testToMap() {
List<user> userList = Arrays.asList(
new User(1L, "mengday"),
new User(2L, "mengdee"),
new User(3L, "mengdy")
);

// toMap 可用于将List转为Map,便于通过key快速查找到某个value
Map<long> userIdAndModelMap = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));
User user = userIdAndModelMap.get(1L);
// User(id=1, username=mengday)
System.out.println(user);

Map<long> userIdAndUsernameMap = userList.stream().collect(Collectors.toMap(User::getId, User::getUsername));
String username = userIdAndUsernameMap.get(1L);
// mengday
System.out.println(username);
}
/<long>/<long>/<user>/<code>

集合元素拼接

<code>@Test
public void testJoining(){
// a,b,c
List<string> list2 = Arrays.asList("a", "b", "c");
String result = list2.stream().collect(Collectors.joining(","));

// Collectors.joining(",")的结果是:a,b,c 然后再将结果 x + "d"操作, 最终返回a,b,cd
String str= Stream.of("a", "b", "c").collect(Collectors.collectingAndThen(Collectors.joining(","), x -> x + "d"));
}
/<string>/<code>

元素聚合

<code>@Test
public void test(){
// 求最值 3
List<integer> list = Arrays.asList(1, 2, 3);
Integer maxValue = list.stream().collect(Collectors.collectingAndThen(Collectors.maxBy((a, b) -> a - b), Optional::get));


// 最小值 1
Integer minValue = list.stream().collect(Collectors.collectingAndThen(Collectors.minBy((a, b) -> a - b), Optional::get));

// 求和 6
Integer sumValue = list.stream().collect(Collectors.summingInt(item -> item));

// 平均值 2.0
Double avg = list.stream().collect(Collectors.averagingDouble(x -> x));
}
/<integer>/<code>
<code>@Test
public void test(){
// 映射:先对集合中的元素进行映射,然后再对映射的结果使用Collectors操作
// A,B,C
Stream.of("a", "b", "c").collect(Collectors.mapping(x -> x.toUpperCase(), Collectors.joining(",")));
}
/<code>

分组

<code>public class User {
private Long id;

private String username;
private Integer type;

// Getter & Setter & toString
}

@Test
public void testGroupBy(){
List<integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 奇偶数分组:奇数分一组,偶数分一组
// groupingBy(Function super T, ? extends K> classifier) 参数是Function类型,Function返回值可以是要分组的条件,也可以是要分组的字段
// 返回的结果是Map,其中key的数据类型为Function体中计算类型,value是List类型,为分组的结果
Map<boolean>> result = list.stream().collect(Collectors.groupingBy(item -> item % 2 == 0));
// {false=[1, 3, 5, 7, 9], true=[2, 4, 6, 8, 10]}
System.out.println(result);


// partitioningBy 用于分成两组的情况
Map<boolean>> twoPartiton = list.stream().collect(Collectors.partitioningBy(item -> item % 2 == 0));
System.out.println(twoPartiton);


User user = new User(1L, "zhangsan", 1);
User user2 = new User(2L, "lisi", 2);
User user3 = new User(3L, "wangwu", 3);
User user4 = new User(4L, "fengliu", 1);
List<user> users = Arrays.asList(user, user2, user3, user4);
// 根据某个字段进行分组
Map<integer>> userGroup = users.stream().collect(Collectors.groupingBy(item -> item.type));

/**
* key 为要分组的字段
* value 分组的结果
* {
* 1=[User{id=1, username='zhangsan', type=1}, User{id=4, username='fengliu', type=1}],
* 2=[User{id=2, username='lisi', type=2}],
* 3=[User{id=3, username='wangwu', type=3}]
* }
*/

System.out.println(userGroup);
}

// 分组并对分组中的数据统计
@Test
public void testGroupBy2() {
Foo foo1 = new Foo(1, 2);
Foo foo2 = new Foo(2, 23);
Foo foo3 = new Foo(2, 6);
List list = new ArrayList<>(4);
list.add(foo1);
list.add(foo2);
list.add(foo3);
Map<integer> collect = list.stream().collect(Collectors.groupingBy(Foo::getCode, Collectors.summarizingInt(Foo::getCount)));
IntSummaryStatistics statistics1 = collect.get(1);
IntSummaryStatistics statistics2 = collect.get(2);
System.out.println(statistics1.getSum());
System.out.println(statistics1.getAverage());
System.out.println(statistics1.getMax());
System.out.println(statistics1.getMin());
System.out.println(statistics1.getCount());

System.out.println(statistics2.getSum());
System.out.println(statistics2.getAverage());
System.out.println(statistics2.getMax());
System.out.println(statistics2.getMin());
System.out.println(statistics2.getCount());
}
/<integer>
/<integer>/<user>/<boolean>/<boolean>
/<integer>/<code>

累计操作

<code>@Test
public void testReducing(){

// sum: 是每次累计计算的结果,b是Function的结果
System.out.println(Stream.of(1, 3, 4).collect(Collectors.reducing(0, x -> x + 1, (sum, b) -> {
System.out.println(sum + "-" + b);
return sum + b;
})));


// 下面代码是对reducing函数功能实现的描述,用于理解reducing的功能

int sum = 0;
List<integer> list3 = Arrays.asList(1, 3, 4);
for (Integer item : list3) {
int b = item + 1;
System.out.println(sum + "-" + b);
sum = sum + b;
}
System.out.println(sum);


// 注意reducing可以用于更复杂的累计计算,加减乘除或者更复杂的操作
// result = 2 * 4 * 5 = 40
System.out.println(Stream.of(1, 3, 4).collect(Collectors.reducing(1, x -> x + 1, (result, b) -> {
System.out.println(result + "-" + b);
return result * b;
})));
}
/<integer>/<code>


分享到:


相關文章: