List<String> items =
Arrays.asList("apple", "apple", "banana",
"apple", "orange", "banana", "papaya");
// 分组
Map<String, List<String>> result1 = items.stream().collect(
Collectors.groupingBy(
Function.identity()
//{papaya=[papaya], orange=[orange], banana=[banana, banana], apple=[apple, apple, apple]}
System.out.println(result1);
// 分组计数
Map<String, Long> result2 = items.stream().collect(
Collectors.groupingBy(
Function.identity(), Collectors.counting()
// {papaya=1, orange=1, banana=2, apple=3}
System.out.println(result2);
Map<String, Long> finalMap = new LinkedHashMap<>();
//分组, 计数和排序
result2.entrySet().stream()
.sorted(Map.Entry.<String, Long>comparingByValue().reversed())
.forEachOrdered(e -> finalMap.put(e.getKey(), e.getValue()));
// {apple=3, banana=2, papaya=1, orange=1}
System.out.println(finalMap);
集合按照多个属性分组
1.多个属性拼接出一个组合属性
public static void main(String[] args) {
User user1 = new User("zhangsan", "beijing", 10);
User user2 = new User("zhangsan", "beijing", 20);
User user3 = new User("lisi", "shanghai", 30);
List<User> list = new ArrayList<User>();
list.add(user1);
list.add(user2);
list.add(user3);
Map<String, List<User>> collect = list.stream().collect(Collectors.groupingBy(e -> fetchGroupKey(e)));
//{zhangsan#beijing=[User{age=10, name='zhangsan', address='beijing'}, User{age=20, name='zhangsan', address='beijing'}],
// lisi#shanghai=[User{age=30, name='lisi', address='shanghai'}]}
System.out.println(collect);
private static String fetchGroupKey(User user){
return user.getName() +"#"+ user.getAddress();
2.嵌套调用groupBy
User user1 = new User("zhangsan", "beijing", 10);
User user2 = new User("zhangsan", "beijing", 20);
User user3 = new User("lisi", "shanghai", 30);
List<User> list = new ArrayList<User>();
list.add(user1);
list.add(user2);
list.add(user3);
Map<String, Map<String, List<User>>> collect
= list.stream().collect(
Collectors.groupingBy(
User::getAddress, Collectors.groupingBy(User::getName)
System.out.println(collect);
3. 使用Arrays.asList
我有一个与Web访问记录相关的域对象列表。这些域对象可以扩展到数千个。
我没有资源或需求将它们以原始格式存储在数据库中,因此我希望预先计算聚合并将聚合的数据放在数据库中。
我需要聚合在5分钟窗口中传输的总字节数,如下面的sql查询
select
round(request_timestamp, '5') as window, --round timestamp to the nearest 5 minute
http_result_code,
transaction_time,
sum(bytes_transferred)
from web_records
group by
round(request_timestamp, '5'),
http_result_code,
transaction_time
在java 8中,我当前的第一次尝试是这样的,我知道这个解决方案类似于Group by multiple field names in java 8
Map<Date, Map<String, Map<String, Map<String, Map<String, Integer>>>>>>> aggregatedData =
webRecords
.stream()
.collect(Collectors.groupingBy(WebRecord::getFiveMinuteWindow,
Collectors.groupingBy(WebRecord::getCdn,
Collectors.groupingBy(WebRecord::getIsp,
Collectors.groupingBy(WebRecord::getResultCode,
Collectors.groupingBy(WebRecord::getTxnTime,
Collectors.reducing(0,
WebRecord::getReqBytes(),
Integer::sum)))))));
这是可行的,但它是丑陋的,所有这些嵌套的地图是一个噩梦!要将地图“展平”或“展开”成行,我必须这样做
for (Date window : aggregatedData.keySet()) {
for (String cdn : aggregatedData.get(window).keySet()) {
for (String isp : aggregatedData.get(window).get(cdn).keySet()) {
for (String resultCode : aggregatedData.get(window).get(cdn).get(isp).keySet()) {
for (String txnTime : aggregatedData.get(window).get(cdn).get(isp).get(resultCode).keySet()) {
Integer bytesTransferred = aggregatedData.get(window).get(cdn).get(distId).get(isp).get(resultCode).get(txnTime);
AggregatedRow row = new AggregatedRow(window, cdn, distId...
如你所见,这是相当混乱和难以维持。
有谁知道更好的方法吗?任何帮助都将不胜感激。
我想知道是否有更好的方法来展开嵌套的映射,或者是否有一个库允许您对集合进行分组。
您应该为地图创建自定义密钥。最简单的方法是使用Arrays.asList:
Function<WebRecord, List<Object>> keyExtractor = wr ->
Arrays.<Object>asList(wr.getFiveMinuteWindow(), wr.getCdn(), wr.getIsp(),
wr.getResultCode(), wr.getTxnTime());
Map<List<Object>, Integer> aggregatedData = webRecords.stream().collect(
Collectors.groupingBy(keyExtractor, Collectors.summingInt(WebRecord::getReqBytes)));
在这种情况下,键是按固定顺序列出的5个元素。不是很面向对象,但很简单。或者,您可以定义自己的表示自定义键的类型,并创建适当的hashCode/equals实现。
参考链接:
Java8的groupingBy实现集合的分组,类似Mysql的group by分组功能,注意得到的是一个map对集合按照单个属性分组、分组计数、排序List<String> items = Arrays.asList("apple", "apple", "banana", "apple", "orange", "ba...
List<TbOrganinfo> organinfo = (List<TbOrganinfo>)JSONObject.parseObject(oil).get("data");
//单个key
Map map = organinfo.stream().collect(Collectors.toMap(TbOrganinfo::getOrganName,Function.identity()));
//两个属性组合作为key
Map map = organinfo.s...
SELECT m.className,m.course
(SELECT AVG(s.score) score,c.className,s.course FROM score s , class c ON s.name = c.name GROUP BY c.className,s.course) m
inner JOIN
(SELECT MAX(t.score) score,t.className
(SELECT AVG(s.score) AS score,c..
Collectors.groupingBy根据一个或多个属性对集合中的项目进行分组
数据准备:
public Product(Long id, Integer num, BigDecimal price, String name, String category) {
this.id = id;
this.num = num;
this.price = price;
this.name = name;
this.category = category;
Product prod1 = ne
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()方法进行了多字段分组和求和操作,代码简洁,可读性强,非常方便。
Centos: 磁盘空间分配,将home空间分配给root
Zeillion:
基于Docker快速搭建 PostgreSQL 高可用方案
今天就努力:
Docker-in-Docker: Jenkins CI 内部如何运行 docker
你的名字有点酸:
iPerf3 命令通用选项
m0_74911788: