在迭代复杂对象时避免嵌套for循环

时间:2016-11-23 18:50:18

标签: java performance

我的应用程序中有一个匹配表,其中包含计划的匹配项的详细信息

enter image description here

我有user表&一个user_match表,它是一个桥接表。

下面的

user_match表格指定了哪个用户遵循哪个匹配&支持哪个团队。 enter image description here

现在,在我的控制器方法中,我将返回今天的预定比赛&如果loggedIn用户遵循今天的预定比赛,也会同时检查。

问题是我必须在进程Complexity O(n ^ 2)中运行两个嵌套for循环。首先,我迭代当天的比赛&然后,对于每一天的比赛,我迭代用户跟随的所有比赛&检查当前匹配是否存在。我希望如果我能摆脱嵌套的for循环,是否有更好的方法来解决这个问题。

@RequestMapping(value="/getTodaysMatches", method=RequestMethod.GET, consumes = "application/json", produces = "application/json")
public @ResponseBody List<Match> getMatchesForCurrentDate(){
    logger.debug("inside /getTodaysMatches CricketController method");

    DateTime currentServerTimeStamp = CricketUtil.getServerDateTime();
    List<Match> currentDayMatchList = this.cricketService.fetchMatchesForInputDate(currentServerTimeStamp);
    CustomUserDetail myUserDetails = currentUserAccessor.getCurrentLoggedInUser();
    User loggedInUser = myUserDetails.getUser();
    List<UserMatchInfo> userMatchInfoList = this.cricketService.getUserMatchInfoByUserId(loggedInUser.getUserId());

    /*check if the logged in user already follows matches scheduled for today*/

    for(Match  todaysMatch : currentDayMatchList){
        for(UserMatchInfo tmpUserMatchInfo : userMatchInfoList){
            String teamFollowedByUser = tmpUserMatchInfo.getSupportingTeam();
            Match matchWhichUserFollows = tmpUserMatchInfo.getMatch();
        if((matchWhichUserFollows.getMatchId().intValue()) == (todaysMatch.getMatchId().intValue())){
            todaysMatch.setLoggedInUserFollowsThisMatch(true);
        }

        if((todaysMatch.getTeamOne().equals(teamFollowedByUser))){
            todaysMatch.setLoggedInUserSupportsTeamOne(true);
        }

        if((todaysMatch.getTeamTwo().equals(teamFollowedByUser))){
            todaysMatch.setLoggedInUserSupportsTeamTwo(true);
        }
      }
    }

    return currentDayMatchList;
}

1 个答案:

答案 0 :(得分:3)

你提供的列表有些笨拙,因为你搜索了Map的ID,它是Object的子节点,因此它看起来像是一个O(n ^ 2)嵌套for循环,当它可以是优化为O(n)。

相反,将ID转换为HashMap,按ID分配给O(n)。

HashMap<Integer, Match> matchMap = new HashMap<>();

for(Match m : currentDayMatchList) {
    int id = m.getMatchId().intValue()
    matchMap.put(id, m);
}

这为我们提供了一个由索引映射的HashMap,以及一个带有ID的键集。现在我们不必一遍又一遍地重复比赛。相反,我们可以做一个O(1)get。

for(UserMatchInfo tmpUserMatchInfo : userMatchInfoList){
    String teamFollowedByUser = tmpUserMatchInfo.getSupportingTeam();
    Match matchWhichUserFollows = tmpUserMatchInfo.getMatch();
    if(matchMap.get(matchWhichUserFollows.getMatchId().intValue()) {
        //... etc.

    }
}

正如您所看到的,for循环已被拆分,因此,不是每次匹配都要执行UserMatch信息,而是先执行UserMatch信息,然后从Map执行O(1),这样性能是O(2n)= O(n)。