为了账号安全,请及时绑定邮箱和手机立即绑定

使用 collect() 而不是 filter() 过滤流

使用 collect() 而不是 filter() 过滤流

蛊毒传说 2022-05-25 16:53:47
我的列表包含看起来像这样的数据game_id | user_id | status   1         1       STARTED   2         1       FINISHED   1         2       STARTED   2         2       FINISHED我想将此列表收集到两个地图中(或者如果可能的话在单个地图中)一张地图应保持与user_id用户玩过的游戏数量的映射 - 基本上是带有finished状态的游戏user_id | finished_games   1            1   2            1另一张地图应存储user_id到所有游戏计数。它看起来像这样user_id  | all_games   1            2   2            2我这样做(我删除了game_id字段,因为它实际上并不重要)import java.util.*;import java.util.stream.*;public class MyClass {    public static void main(String args[]) {        List<Game> games = Arrays.asList(            create("user-1", "STARTED"),            create("user-2", "STARTED"),            create("user-1", "FINISHED"),            create("user-2", "FINISHED"),            create("user-1", "FINISHED"),            create("user-2", "FINISHED")        );        // expect user-1: all_games (3), finished_games (2)        Map<String, Long> allGames = games            .stream()            .collect(Collectors.groupingBy(Game::getUserId, Collectors.counting()));        System.out.println(allGames);        Map<String, Long> finishedGames = games            .stream()            .filter(game -> game.battleStatus.equals("FINISHED"))            .collect(Collectors.groupingBy(Game::getUserId, Collectors.counting()));        System.out.println(finishedGames);    }    private static Game create(String id, String status) {        Game game = new Game();        game.userId = id;        game.battleStatus = status;        return game;    }    private static class Game {        String userId;        String battleStatus;        public String getUserId() {            return userId;        }    }}它似乎工作正常。但是当我计算带有状态的游戏时,我会进行过滤以便只留下带有FINISHED状态的项目。Map<String, Long> finishedGames = games    .stream()    .filter(game -> game.battleStatus.equals("FINISHED"))    .collect(Collectors.groupingBy(Game::getUserId, Collectors.counting()));有没有办法实现内部collect块而不是使用filter?
查看完整描述

2 回答

?
扬帆大鱼

TA贡献1799条经验 获得超9个赞

您可以使用多个groupingBy来获得这个,例如:


Map<String, Map<String, Long>> gameStatuses = games

   .stream()

   .collect(Collectors.groupingBy(Game::getUserId, 

   Collectors.groupingBy(Game::getBattleStatus, Collectors.counting())));

System.out.println(gameStatuses);

为此,您需要为Game类添加一个吸气剂battleStatus,例如:


private static class Game {

    String userId;

    String battleStatus;


    public String getUserId() {

        return userId;

    }


    public String getBattleStatus() {

        return battleStatus;

    }

}

这将为您提供以下输出:


{user-1={STARTED=1, FINISHED=2}, user-2={STARTED=1, FINISHED=2}}

您可以使用嵌套map.get来获取任何用户和任何状态的计数。


查看完整回答
反对 回复 2022-05-25
?
ibeautiful

TA贡献1993条经验 获得超5个赞

如果您需要计算已完成和未完成的游戏,那么另一个groupingBy可以帮助您:


Function<Game, Boolean> isFinished = game -> "FINISHED".equals(game.battleStatus);


Map<String, Map<Boolean, Long>> groupedGames = 

    games.stream()

         .collect(groupingBy(Game::getUserId, 

                      groupingBy(isFinished, counting())));

或者您可能想自己分组battleStatus:


Map<String, Map<String, Long>> groupedGames = 

    games.stream()

         .collect(groupingBy(Game::getUserId, 

                      groupingBy(game -> game.battleStatus, counting())));

我什至会创建一个吸气剂getBattleStatus(),然后game -> game.battleStatus用方法参考替换Game::getBattleStatus:


Map<String, Map<String, Long>> groupedGames = 

    games.stream()

         .collect(groupingBy(Game::getUserId, 

                      groupingBy(Game::getBattleStatus, counting())));


查看完整回答
反对 回复 2022-05-25
  • 2 回答
  • 0 关注
  • 90 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号