精华内容
下载资源
问答
  • Java8 stream 之groupingBy() 分组排序

    万次阅读 热门讨论 2017-12-29 12:06:37
    List matchsList = new ArrayList();... MatchsListMap = matchsList.stream() .collect(Collectors.groupingBy(Matchs::getMatchDate)); 此时MatchsListMap的排序规则是根据MatchDate降序的(默认),也就是说ma
    	List<Matchs> matchsList = new ArrayList();
    	
    	Map<String,List<Matchs>> MatchsListMap=matchsList.stream()
    	.collect(Collectors.groupingBy(Matchs::getMatchDate));	
    

    此时MatchsListMap的排序规则是根据Hash值排序一般来讲认为是无序即可,那么如果需要根据MatchDate升/降序该怎么办呢?

    答案是:

    
    TreeMap<String, List<Matchs>> matchsListMap = matchsList.stream()
    .collect(Collectors.groupingBy(Matchs::getMatchDate,TreeMap::new,Collectors.toList()));
    
    

    此时返回的为TreeMap类型数据,TreeMap默认为按照key升序,matchsListMap.descendingMap()可以降序输出

    2021年1月4日 19:53:19
    补充另一种修改比较器的写法

    List<Integer> resultList = IntStream.rangeClosed(1, 24).map(operand -> 0).boxed().collect(Collectors.toList());
            resultList.set(1,9);
            resultList.set(3,3);
            resultList.set(7,22);
            TreeMap<Integer, List<Integer>> collect = resultList.stream()
                    .collect(Collectors.groupingBy(Function.identity(), () -> {
                        Comparator<Integer> comparing = Comparator.comparing(Function.identity());
                        return new TreeMap<>(comparing.reversed());
                    }, Collectors.toList()));
    
    展开全文
  • java8中的Collectors.groupingBy用法

    万次阅读 多人点赞 2019-10-13 18:21:54
    Collectors.groupingBy根据一个或多个属性对集合中的项目进行分组 数据准备: public Product(Long id, Integer num, BigDecimal price, String name, String category) { this.id = id; this.num = num; ...

    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 = new Product(1L, 1, new BigDecimal("15.5"), "面包", "零食");
    Product prod2 = new Product(2L, 2, new BigDecimal("20"), "饼干", "零食");
    Product prod3 = new Product(3L, 3, new BigDecimal("30"), "月饼", "零食");
    Product prod4 = new Product(4L, 3, new BigDecimal("10"), "青岛啤酒", "啤酒");
    Product prod5 = new Product(5L, 10, new BigDecimal("15"), "百威啤酒", "啤酒");
    List<Product> prodList = Lists.newArrayList(prod1, prod2, prod3, prod4, prod5);
    
    

    分组

    • 按照类目分组:
    Map<String, List<Product>> prodMap= prodList.stream().collect(Collectors.groupingBy(Product::getCategory));
    
    //{"啤酒":[{"category":"啤酒","id":4,"name":"青岛啤酒","num":3,"price":10},{"category":"啤酒","id":5,"name":"百威啤酒","num":10,"price":15}],"零食":[{"category":"零食","id":1,"name":"面包","num":1,"price":15.5},{"category":"零食","id":2,"name":"饼干","num":2,"price":20},{"category":"零食","id":3,"name":"月饼","num":3,"price":30}]}
    
    
    • 按照几个属性拼接分组:
    Map<String, List<Product>> prodMap = prodList.stream().collect(Collectors.groupingBy(item -> item.getCategory() + "_" + item.getName()));
    
    //{"零食_月饼":[{"category":"零食","id":3,"name":"月饼","num":3,"price":30}],"零食_面包":[{"category":"零食","id":1,"name":"面包","num":1,"price":15.5}],"啤酒_百威啤酒":[{"category":"啤酒","id":5,"name":"百威啤酒","num":10,"price":15}],"啤酒_青岛啤酒":[{"category":"啤酒","id":4,"name":"青岛啤酒","num":3,"price":10}],"零食_饼干":[{"category":"零食","id":2,"name":"饼干","num":2,"price":20}]}
    
    
    • 根据不同条件分组
    Map<String, List<Product>> prodMap= prodList.stream().collect(Collectors.groupingBy(item -> {
    	if(item.getNum() < 3) {
    		return "3";
    	}else {
    		return "other";
    	}
    }));
    
    //{"other":[{"category":"零食","id":3,"name":"月饼","num":3,"price":30},{"category":"啤酒","id":4,"name":"青岛啤酒","num":3,"price":10},{"category":"啤酒","id":5,"name":"百威啤酒","num":10,"price":15}],"3":[{"category":"零食","id":1,"name":"面包","num":1,"price":15.5},{"category":"零食","id":2,"name":"饼干","num":2,"price":20}]}
    
    

    多级分组

    要实现多级分组,我们可以使用一个由双参数版本的Collectors.groupingBy工厂方法创 建的收集器,它除了普通的分类函数之外,还可以接受collector类型的第二个参数。那么要进 行二级分组的话,我们可以把一个内层groupingBy传递给外层groupingBy,并定义一个为流 中项目分类的二级标准。

    Map<String, Map<String, List<Product>>> prodMap= prodList.stream().collect(Collectors.groupingBy(Product::getCategory, Collectors.groupingBy(item -> {
    	if(item.getNum() < 3) {
    		return "3";
    	}else {
    		return "other";
    	}
    })));
    
    //{"啤酒":{"other":[{"category":"啤酒","id":4,"name":"青岛啤酒","num":3,"price":10},{"category":"啤酒","id":5,"name":"百威啤酒","num":10,"price":15}]},"零食":{"other":[{"category":"零食","id":3,"name":"月饼","num":3,"price":30}],"3":[{"category":"零食","id":1,"name":"面包","num":1,"price":15.5},{"category":"零食","id":2,"name":"饼干","num":2,"price":20}]}}
    
    

    按子组收集数据

    • 求总数
    Map<String, Long> prodMap = prodList.stream().collect(Collectors.groupingBy(Product::getCategory, Collectors.counting()));
    
    //{"啤酒":2,"零食":3}
    
    • 求和
    Map<String, Integer> prodMap = prodList.stream().collect(Collectors.groupingBy(Product::getCategory, Collectors.summingInt(Product::getNum)));
    
    //{"啤酒":13,"零食":6}
    
    • 把收集器的结果转换为另一种类型
    Map<String, Product> prodMap = prodList.stream().collect(Collectors.groupingBy(Product::getCategory, Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingInt(Product::getNum)), Optional::get)));
    
    //{"啤酒":{"category":"啤酒","id":5,"name":"百威啤酒","num":10,"price":15},"零食":{"category":"零食","id":3,"name":"月饼","num":3,"price":30}}
    
    
    • 联合其他收集器
    Map<String, Set<String>> prodMap = prodList.stream().collect(Collectors.groupingBy(Product::getCategory, Collectors.mapping(Product::getName, Collectors.toSet())));
    
    //{"啤酒":["青岛啤酒","百威啤酒"],"零食":["面包","饼干","月饼"]}
    
    

    相关链接:
    java8中map新增方法详解
    java8中Stream的使用
    java8中Collection新增方法详解
    java8中Collectors的方法使用实例
    java8中常用函数式接口
    java8中的方法引用和构造函数引用
    java8中的Collectors.groupingBy用法
    java8中的Optional用法
    java8中的日期和时间API

    展开全文
  • } Map, List<User>> userMap = userList.stream().collect(Collectors.groupingBy(User::getDate, LinkedHashMap::new, Collectors.toList())); System.out.println(userMap); } 可以看到分完组的Map变成有序的了 ...

    先创建个实体

    @Data
    public class User {
        private String date;
        private String name;
        private String age;
    
        public User(String date, String name, String age) {
            this.date = date;
            this.name = name;
            this.age = age;
        }
    }
    

    按日期分下组

        public static void main(String[] args) {
            List<User> userList = new ArrayList<>();
            for (int x = 1; x < 30; x++) {
                User user = new User("2021-06-" + (x < 10 ? "0" + x : x), "张三", x);
                userList.add(user);
            }
    
            Map<String, List<User>> userMap = userList.stream().collect(Collectors.groupingBy(User::getDate));
            System.out.println(userMap);
        }
    

    可以看到分完组的Map顺序是乱的
    在这里插入图片描述
    这个方法为什么会乱序,看下源码

        public static <T, K, A, D>
        Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
                                              Collector<? super T, A, D> downstream) {
            return groupingBy(classifier, HashMap::new, downstream);
        }
    

    可以看到,这个方法默认返回的是HashMap,都知道HashMap是无序的,既然找到问题就好解决了,我们手动传个有序的Map进去就可以了

        public static void main(String[] args) {
            List<User> userList = new ArrayList<>();
            for (int x = 1; x < 30; x++) {
                User user = new User("2021-06-" + (x < 10 ? "0" + x : x), "张三", x);
                userList.add(user);
            }
    
            Map<String, List<User>> userMap = userList.stream().collect(Collectors.groupingBy(User::getDate, LinkedHashMap::new, Collectors.toList()));
            System.out.println(userMap);
        }
    

    可以看到分完组的Map变成有序的了
    在这里插入图片描述

    也可以额外的去除排序

    		// 将日期key取出,去重、排序
            List<String> dateList = new ArrayList<>(userMap.keySet());
            dateList = dateList.stream().distinct().collect(Collectors.toList());
            Collections.sort(dateList);
    
    展开全文
  • java stream groupingBy.pdf

    2021-08-26 14:40:58
    java stream groupingBy.pdf
  • 介绍 Java 8 groupingBy Collector

    万次阅读 2019-04-24 22:52:55
    介绍 Java 8 groupingBy Collector 本文我们探讨下Java 8 groupingBy Collector,通过不同的示例进行详细讲解。 GroupingBy Collector Java 8 Stream API 提供了声明方式处理流数据。static工厂方法Collectors....

    介绍 Java 8 groupingBy Collector

    本文我们探讨下Java 8 groupingBy Collector,通过不同的示例进行详细讲解。

    GroupingBy Collector

    Java 8 Stream API 提供了声明方式处理流数据。static工厂方法Collectors.groupingBy() 和 Collectors.groupingByConcurrent() 实现类似SQL语句的“Group By”字句功能,实现根据一些属性进行分组并把结果存在Map实例。

    重载groupingBy的几个方法:

    static <T,K> Collector<T,?,Map<K,List<T>>> 
      groupingBy(Function<? super T,? extends K> classifier)
    

    提供后续收集器参数:

    static <T,K,A,D> Collector<T,?,Map<K,D>>
      groupingBy(Function<? super T,? extends K> classifier, 
        Collector<? super T,A,D> downstream)
    

    提供map 提供者和后续收集器参数:

    static <T,K,D,A,M extends Map<K,D>> Collector<T,?,M>
      groupingBy(Function<? super T,? extends K> classifier, 
        Supplier<M> mapFactory, Collector<? super T,A,D> downstream)
    

    下面通过示例详细看看每个方法的应用场景。

    基础准备

    为了演示groupingBy(),让我们定义BlogPost类(作为流使用):

    class BlogPost {
        String title;
        String author;
        BlogPostType type;
        int likes;
    }
    

    BlogPostType:

    enum BlogPostType {
        NEWS,
        REVIEW,
        GUIDE
    }
    

    定义一个BlogPost列表:

    List<BlogPost> posts = Arrays.asList( ... );
    

    同时也订一个Tuple类用于根据多个属性进行分组:

    class Tuple {
        BlogPostType type;
        String author;
    }
    

    通过单个属性简单分组

    首先从最简单的groupingBy 方法开始,使用一个分类函数作为参数。分类函数应用于流中的每个元素。函数的返回值用于map的key,映射至分组集合。根据post类型进行分组的代码:

    Map<BlogPostType, List<BlogPost>> postsPerType = posts.stream()
      .collect(groupingBy(BlogPost::getType));
    

    根据复杂类型进行分组

    Map<Tuple, List<BlogPost>> postsPerTypeAndAuthor = posts.stream()
      .collect(groupingBy(post -> new Tuple(post.getType(), post.getAuthor())));
    

    分组类型不限于标量或字符串类型。map的key可以是任何对象类型,只有我们确保实现必要的equals 和 hashcode 方法。下面根据组合类型进行分组:

    Map<Tuple, List<BlogPost>> postsPerTypeAndAuthor = posts.stream()
      .collect(groupingBy(post -> new Tuple(post.getType(), post.getAuthor())));
    

    修改返回Map值类型

    第二个重载groupingBy方法带另一个参数指定后续收集器,应用于第一个集合结果。当我们仅指定一个分类器函数,没有后续收集器,则返回toList()集合。如何后续收集器使用toSet(),则会获得Set集合,而不是List:

    Map<BlogPostType, Set<BlogPost>> postsPerType = posts.stream()
      .collect(groupingBy(BlogPost::getType, toSet()));
    

    根据多个字段进行分组

    与应用后续收集器不同的是,可以指定第二个分类器对第一个分组结果再分组。对BlogPost类的List根据作者和类型进行分组代码如下:

    Map<String, Map<BlogPostType, List>> map = posts.stream()
      .collect(groupingBy(BlogPost::getAuthor, groupingBy(BlogPost::getType)));
    

    获取分组结果的平均值

    通过使用后续收集器可以对分组函数的结果使用聚集函数。获取每种blog类型的平均数:

    Map<BlogPostType, Double> averageLikesPerType = posts.stream()
      .collect(groupingBy(BlogPost::getType, averagingInt(BlogPost::getLikes)));
    

    获取分组结果之和

    计算每个分组之和:

    Map<BlogPostType, Integer> likesPerType = posts.stream()
      .collect(groupingBy(BlogPost::getType, summingInt(BlogPost::getLikes)));
    

    获取分组结果的最大值和最小值

    另外可以通过聚集函数获取最大数量的blog类型:

    Map<BlogPostType, Optional<BlogPost>> maxLikesPerPostType = posts.stream()
      .collect(groupingBy(BlogPost::getType,
      maxBy(comparingInt(BlogPost::getLikes))));
    

    类似的,我们能应用minBy后续收集器获得最小数量的分类。注意,maxBy和minBy 收集器考虑到应用它的集合可能是空的。这就是为什么map中的值类型是可选的。

    获取属性分组结果的摘要信息

    Collectors API提供了摘要收集器,用于需要同时获取数值属性的count,sum, minimum, maximum ,average 值。下面计算每种类型的摘要信息:

    Map<BlogPostType, IntSummaryStatistics> likeStatisticsPerType = posts.stream()
      .collect(groupingBy(BlogPost::getType, 
      summarizingInt(BlogPost::getLikes)));
    

    每个类型的IntSummaryStatistics 对象包括属性的 count, sum, average, min 和 max值。另外摘要对象也有double和long类型。

    映射分组结果至不同类型

    更复杂的聚集可以对分类结果应用后续映射收集器。下面获得每个类型的连接blog的标题。

    Map<BlogPostType, String> postsPerType = posts.stream()
      .collect(groupingBy(BlogPost::getType, 
      mapping(BlogPost::getTitle, joining(", ", "Post titles: [", "]"))));
    

    上面代码实现映射每个BlogPost 实例至title,然后reduce 文章标题流至连接字符串。本例Map的值是字符串,而不是默认List类型。

    修改返回 Map 类型

    当使用groupingBy 收集器,我们不能确定返回Map的类型。如果我们想指定特定Map类型作为返回值,我们使用三个参数的groupingBy 方法,通过提供Map supplier函数,其允许我们改变Map的类型。

    通过EnumMap supplier函数给goupingBy方法获取EnumMap:

    EnumMap<BlogPostType, List<BlogPost>> postsPerType = posts.stream()
      .collect(groupingBy(BlogPost::getType, 
      () -> new EnumMap<>(BlogPostType.class), toList()));
    

    并发Grouping By Collector

    类似于 groupingBy, 也有groupingByConcurrent 收集器,其利用多线程架构。其有三个重载方法,带有与groupingBy一样的参数。然而,groupingByConcurrent 收集器的返回值必须是ConcurrentHashMap 类或其子类。

    实现并发分组的代码如下:

    ConcurrentMap<BlogPostType, List<BlogPost>> postsPerType = posts.parallelStream()
      .collect(groupingByConcurrent(BlogPost::getType));
    

    如果你选择传递Map supplier函数给groupingByConcurrent 收集器,那么需要确保函数返回值也必须是ConcurrentHashMap 类或其子类。

    总结

    本文我们看了Java 8 中提供的几个groupingBy collector示例。groupingBy可以对流元素根据其属性进行分组,然后进一步收集、改变并收集至最终的容器中。

    展开全文
  • java8 分组计数 Collectors.groupingBy Collectors.counting //分组计数 Map<String, Long> colorNum = appleList.stream().collect(Collectors.groupingBy(Apple::getColor, Collecto...
  • duplicates = notificationServiceOrderItemDto.getService().getServiceCharacteristics().stream().collect(Collectors.groupingBy(ServiceCharacteristicDto::getName, Collectors.counting())).entry...
  • 主要是介绍在 JDK8中使用 stream 流的 groupingBy 方法源进行最大值分组、最小值分组、平均值分组、统计分组
  • Collectors.groupingBy

    2021-09-08 15:53:03
    Collectors.groupingBy根据一个或多个属性对集合中的项目进行分组 代码如下: public class ListToMapTest { public static void main(String[] args) throws ParseException { List<User> users = ...
  • Java8 Stream 之groupingBy 分组讲解.pdf
  • Collectors.groupingBy 使用

    千次阅读 2020-06-03 00:43:38
    本文主要介绍一下lambda表达式中的Collectors.groupingBy的使用。 //groupingBy使用 System.out.println("=======groupingBy=========="); Stream<Person> stream = Stream.of(new Person("1", "aa", "12...
  • Java8 Stream groupingBy对List进行分组

    万次阅读 多人点赞 2018-11-03 14:37:04
    其实Java8 Streams API中的Collector也支持流中的数据进行分组和分区操作,本片文章讲简单介绍一下,如何使用groupingBy 和 partitioningBy来对流中的元素进行分组和分区。 groupingBy 首先看一下Java8之前如果...
  • 主要介绍了Java8 stream 中利用 groupingBy 进行多字段分组求和案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • Java Stream API groupingBy()介绍

    万次阅读 2019-09-02 01:45:25
    groupingBy()是Stream API中最强大的收集器Collector之一,提供与SQL的GROUP BY子句类似的功能。 使用形式如下: .collect(groupingBy(...)); 需要指定一个属性才能使用,通过该属性执行分组。...
  • Java8 stream 中利用 groupingBy 进行多字段分组求和

    万次阅读 多人点赞 2020-01-16 15:49:19
    Java8的groupingBy实现集合的分组,类似Mysql的group by分组功能,注意得到的是一个map 对集合按照单个属性分组、分组计数、排序 List<String> items = Arrays.asList("apple", "apple", "banana", ...
  • groupingBy​(Function<? super T,​? extends K> classifier) public static <T,​K,​A,​D> Collector<T,​?,​Map<K,​D>> groupingBy​(Function<? super T,​? exten
  • JAVA8 Collectors.groupingBy

    2019-12-28 20:07:50
    1.按长度对字符串进行分组 List<String> list = Arrays.asList("a", "bb", "cc", "ddd"); Map<... result = list.stream().collect(Collectors.groupingBy(String::length)); System.ou...
  • 今天在写一个功能的时候用到了Dictionary 的 grouping by 这个用法,代码先贴出来 import UIKit class AlignFlowLayout: UICollectionViewFlowLayout { required init(itemSize: CGSize = CGSize.zero, ...
  • java stream groupingBy(classifier, downstream, mapFactory).pdf
  • Stream Java8 API新出的语法,以一种声明式的方式处理数据,类似于SQL,更直观,是对Java集合...分组 groupingBy 模拟数据,实际中可以是数据库、网络数据、本地文件数据等 学生基本信息: Student(sid=11, name=张三
  • stream 中的groupingBy 和partitioningBy

    千次阅读 2017-07-31 23:56:57
    stream 中的groupingBy 和partitioningBy

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 36,865
精华内容 14,746
关键字:

groupingby