Java8 Stream 之groupingBy 分组讲解

本文主要讲解:Java 8 Stream之Collectors.groupingBy()分组示例

Collectors.groupingBy() 分组之常见用法

功能代码:

/**
	 * 使用java8 stream groupingBy操作,按城市分组list
	 */
	public void groupingByCity() {
		Map<String, List<Employee>> map = employees.stream().collect(Collectors.groupingBy(Employee::getCity));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
		});
	}

Collectors.groupingBy() 分组之统计每个分组的count

功能代码:

/**
	 * 使用java8 stream groupingBy操作,按城市分组list统计count
	 */
	public void groupingByCount() {
		Map<String, Long> map = employees.stream()
				.collect(Collectors.groupingBy(Employee::getCity, Collectors.counting()));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
		});
	}

Collectors.groupingBy() 分组之统计分组平均值

功能代码:

/**
	 * 使用java8 stream groupingBy操作,按城市分组list并计算分组年龄平均值
	 */
	public void groupingByAverage() {
		Map<String, Double> map = employees.stream()
				.collect(Collectors.groupingBy(Employee::getCity, Collectors.averagingInt(Employee::getAge)));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
		});
	}

Collectors.groupingBy() 分组之统计分组总值

功能代码:

/**
	 * 使用java8 stream groupingBy操作,按城市分组list并计算分组销售总值
	 */
	public void groupingBySum() {
		Map<String, Long> map = employees.stream()
				.collect(Collectors.groupingBy(Employee::getCity, Collectors.summingLong(Employee::getAmount)));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
		});

		// 对Map按照分组销售总值逆序排序
		Map<String, Long> sortedMap = new LinkedHashMap<>();
		map.entrySet().stream().sorted(Map.Entry.<String, Long> comparingByValue().reversed())
				.forEachOrdered(e -> sortedMap.put(e.getKey(), e.getValue()));

		sortedMap.forEach((k, v) -> {
			System.out.println(k + " = " + v);
		});
	}

Collectors.groupingBy() 分组之Join分组List

功能代码:

/**
	 * 使用java8 stream groupingBy操作,按城市分组list并通过join操作连接分组list中的对象的name 属性使用逗号分隔
	 */
	public void groupingByString() {
		Map<String, String> map = employees.stream().collect(Collectors.groupingBy(Employee::getCity,
				Collectors.mapping(Employee::getName, Collectors.joining(", ", "Names: [", "]"))));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
		});
	}

Collectors.groupingBy() 分组之转换分组结果List -> List

功能代码:

/**
	 * 使用java8 stream groupingBy操作,按城市分组list,将List转化为name的List
	 */
	public void groupingByList() {
		Map<String, List<String>> map = employees.stream().collect(
				Collectors.groupingBy(Employee::getCity, Collectors.mapping(Employee::getName, Collectors.toList())));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
			v.stream().forEach(item -> {
				System.out.println("item = " + item);
			});
		});
	}

Collectors.groupingBy() 分组之转换分组结果List -> Set

功能代码:

/**
	 * 使用java8 stream groupingBy操作,按城市分组list,将List转化为name的Set
	 */
	public void groupingBySet() {
		Map<String, Set<String>> map = employees.stream().collect(
				Collectors.groupingBy(Employee::getCity, Collectors.mapping(Employee::getName, Collectors.toSet())));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
			v.stream().forEach(item -> {
				System.out.println("item = " + item);
			});
		});
	}

Collectors.groupingBy() 分组之使用对象分组List

功能代码:

/**
	 * 使用java8 stream groupingBy操作,通过Object对象的成员分组List
	 */
	public void groupingByObject() {
		Map<Manage, List<Employee>> map = employees.stream().collect(Collectors.groupingBy(item -> {
			return new Manage(item.getName());
		}));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
		});
	}

Collectors.groupingBy() 分组之使用两个成员分组List

功能代码:

/**
	 * 使用java8 stream groupingBy操作, 基于city 和name 实现多次分组
	 */
	public void groupingBys() {
		Map<String, Map<String, List<Employee>>> map = employees.stream()
				.collect(Collectors.groupingBy(Employee::getCity, Collectors.groupingBy(Employee::getName)));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
			v.forEach((i, j) -> {
				System.out.println(i + " = " + j);
			});
		});
	}

自定义Distinct对结果去重

功能代码

/**
	 * 使用java8 stream groupingBy操作, 基于Distinct 去重数据
	 */
	public void groupingByDistinct() {
		List<Employee> list = employees.stream().filter(distinctByKey(Employee :: getCity))
				.collect(Collectors.toList());;

		list.stream().forEach(item->{
			System.out.println("city = " + item.getCity());
		});
		
		
	}

	/**
	 * 自定义重复key 规则
	 * @param keyExtractor
	 * @return
	 */
	private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
		Set<Object> seen = ConcurrentHashMap.newKeySet();
		return t -> seen.add(keyExtractor.apply(t));
	}

完整源代码:

package com.stream;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * Java 8 Stream 之groupingBy 分组讲解
 * 
 * @author zzg
 *
 */
public class Java8GroupBy {

	List<Employee> employees = new ArrayList<Employee>();

	/**
	 * 数据初始化
	 */
	public void init() {
		List<String> citys = Arrays.asList("湖南", "湖北", "江西", "广西 ");
		for (int i = 0; i < 10; i++) {
			Random random = new Random();
			Integer index = random.nextInt(4);
			Employee employee = new Employee(citys.get(index), "姓名" + i, (random.nextInt(4) * 10 - random.nextInt(4)),
					(random.nextInt(4) * 1000 - random.nextInt(4)));
			employees.add(employee);
		}
	}

	/**
	 * 使用java8 stream groupingBy操作,按城市分组list
	 */
	public void groupingByCity() {
		Map<String, List<Employee>> map = employees.stream().collect(Collectors.groupingBy(Employee::getCity));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
		});
	}

	/**
	 * 使用java8 stream groupingBy操作,按城市分组list统计count
	 */
	public void groupingByCount() {
		Map<String, Long> map = employees.stream()
				.collect(Collectors.groupingBy(Employee::getCity, Collectors.counting()));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
		});
	}

	/**
	 * 使用java8 stream groupingBy操作,按城市分组list并计算分组年龄平均值
	 */
	public void groupingByAverage() {
		Map<String, Double> map = employees.stream()
				.collect(Collectors.groupingBy(Employee::getCity, Collectors.averagingInt(Employee::getAge)));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
		});
	}

	/**
	 * 使用java8 stream groupingBy操作,按城市分组list并计算分组销售总值
	 */
	public void groupingBySum() {
		Map<String, Long> map = employees.stream()
				.collect(Collectors.groupingBy(Employee::getCity, Collectors.summingLong(Employee::getAmount)));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
		});

		// 对Map按照分组销售总值逆序排序
		Map<String, Long> sortedMap = new LinkedHashMap<>();
		map.entrySet().stream().sorted(Map.Entry.<String, Long> comparingByValue().reversed())
				.forEachOrdered(e -> sortedMap.put(e.getKey(), e.getValue()));

		sortedMap.forEach((k, v) -> {
			System.out.println(k + " = " + v);
		});
	}

	/**
	 * 使用java8 stream groupingBy操作,按城市分组list并通过join操作连接分组list中的对象的name 属性使用逗号分隔
	 */
	public void groupingByString() {
		Map<String, String> map = employees.stream().collect(Collectors.groupingBy(Employee::getCity,
				Collectors.mapping(Employee::getName, Collectors.joining(", ", "Names: [", "]"))));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
		});
	}

	/**
	 * 使用java8 stream groupingBy操作,按城市分组list,将List转化为name的List
	 */
	public void groupingByList() {
		Map<String, List<String>> map = employees.stream().collect(
				Collectors.groupingBy(Employee::getCity, Collectors.mapping(Employee::getName, Collectors.toList())));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
			v.stream().forEach(item -> {
				System.out.println("item = " + item);
			});
		});
	}

	/**
	 * 使用java8 stream groupingBy操作,按城市分组list,将List转化为name的Set
	 */
	public void groupingBySet() {
		Map<String, Set<String>> map = employees.stream().collect(
				Collectors.groupingBy(Employee::getCity, Collectors.mapping(Employee::getName, Collectors.toSet())));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
			v.stream().forEach(item -> {
				System.out.println("item = " + item);
			});
		});
	}

	/**
	 * 使用java8 stream groupingBy操作,通过Object对象的成员分组List
	 */
	public void groupingByObject() {
		Map<Manage, List<Employee>> map = employees.stream().collect(Collectors.groupingBy(item -> {
			return new Manage(item.getName());
		}));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
		});
	}

	/**
	 * 使用java8 stream groupingBy操作, 基于city 和name 实现多次分组
	 */
	public void groupingBys() {
		Map<String, Map<String, List<Employee>>> map = employees.stream()
				.collect(Collectors.groupingBy(Employee::getCity, Collectors.groupingBy(Employee::getName)));

		map.forEach((k, v) -> {
			System.out.println(k + " = " + v);
			v.forEach((i, j) -> {
				System.out.println(i + " = " + j);
			});
		});
	}

	/**
	 * 使用java8 stream groupingBy操作, 基于Distinct 去重数据
	 */
	public void groupingByDistinct() {
		List<Employee> list = employees.stream().filter(distinctByKey(Employee :: getCity))
				.collect(Collectors.toList());;

		list.stream().forEach(item->{
			System.out.println("city = " + item.getCity());
		});
		
		
	}

	/**
	 * 自定义重复key 规则
	 * @param keyExtractor
	 * @return
	 */
	private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
		Set<Object> seen = ConcurrentHashMap.newKeySet();
		return t -> seen.add(keyExtractor.apply(t));
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Java8GroupBy instance = new Java8GroupBy();
		instance.init();
		instance.groupingByCity();
		instance.groupingByCount();
		instance.groupingByAverage();
		instance.groupingBySum();
		instance.groupingByString();
		instance.groupingByList();
		instance.groupingBySet();
		instance.groupingByObject();
		instance.groupingBys();
		instance.groupingByDistinct();

	}

	class Employee {
		private String city;
		private String name;
		private Integer age;
		private Integer amount;

		public String getCity() {
			return city;
		}

		public void setCity(String city) {
			this.city = city;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public Integer getAge() {
			return age;
		}

		public void setAge(Integer age) {
			this.age = age;
		}

		public Integer getAmount() {
			return amount;
		}

		public void setAmount(Integer amount) {
			this.amount = amount;
		}

		public Employee(String city, String name, Integer age, Integer amount) {
			super();
			this.city = city;
			this.name = name;
			this.age = age;
			this.amount = amount;
		}

		public Employee() {
			super();
		}
	}

	class Manage {
		private String name;

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public Manage(String name) {
			super();
			this.name = name;
		}

		public Manage() {
			super();
		}
	}

}

github 地址: 待补全

本文参考:

Java8 Stream groupingBy对List进行分组

Java 8引入了Stream API,有许多新方法,其中有一个对于分组和聚合操作非常有用,那就是groupingBy()方法。它可以将一个流分组成一个Map,其中Entry的key是分组的条件,value是分组的结果,通常是一个List或其他集合。groupingBy()方法的另一个形式是groupingByConcurrent(),它返回一个并发Map,对于并发访问更加友好。 利用groupingBy()方法进行多字段分组和求和操作的示例如下: 假设有一个Person类,其中包含属性:name, age和salary。现在我们需要根据name和age两个字段进行分组,并求出每组的salary总和。可以使用groupingBy()方法加上summingDouble()方法来实现: ``` List<Person> persons = Arrays.asList( new Person("Tom", 20, 5000), new Person("Tom", 21, 4000), new Person("Jerry", 22, 6000), new Person("Jerry", 23, 5500), new Person("Kate", 24, 7000), new Person("Kate", 25, 8000) ); Map<String, Map<Integer, Double>> result = persons.stream() .collect(Collectors.groupingBy(Person::getName, Collectors.groupingBy(Person::getAge, Collectors.summingDouble(Person::getSalary)))); ``` 这里的personList是一个包含了6个Person对象的List,我们希望将其中相同name和age的对象分组,求得salary的总和。在groupingBy()方法中,第一个参数是分组条件,这里是Person::getName,第二个参数是分组的结果,这里是一个嵌套的groupingBy()方法,用于再次按照age进行分组,结果是一个Map<Integer, Double>。最后,我们使用summingDouble()方法对salary字段进行求和,得到各个分组的salary总和。这里的result是一个Map<String, Map<Integer, Double>>类型的对象,其中key是name,value是以age为key,salary总和为value的子Map,就是我们需要的结果。 这样,我们就利用Java 8中的Stream API和groupingBy()方法进行了多字段分组和求和操作,代码简洁,可读性强,非常方便。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值