我作为程序员最大的错误 - 对于循环



我认为这是我最大的错误,我开始意识到我已经在我的网络应用程序中重复了很多次。

每次我想比较列表中的一个属性是否与列表中的另一个属性相同时,我都会做一个双精度的 for 循环。

当然,这对我的网站来说还不错,但是一旦它拥有数百万用户,它就会开始变慢。

这是我的典型错误:

在这种情况下,我有一个包含已登录用户的用户名的List<String>,我想将每个用户的完整用户信息返回到前端。

这似乎很糟糕,因为我需要遍历所有用户,即使我只需要获取在线用户的信息。

谁能帮我解决这个问题?这是不好的做法吗?我能做什么?

 @Autowired
private ActiveUsers activeUsers;
 @RequestMapping(value = "/loggedUsers", method = RequestMethod.GET)
public @ResponseBody List<User> getLoggedUsers() {
    List<User> users = User.getUsers();
    List<User> onlineUsers = new ArrayList<>();
    for(User user : users) {
        for(String username : activeUsers.getUsers()) {
            if(username.equals(user.getUsername())) {
                onlineUsers.add(user);
            }
        }
    }
    return onlineUsers;
}

使用Map<String,User> .User.getUsers()返回该Map(可能应该缓存它,这样您就不必在每次调用该方法时都生成该Map(。键将是用户名,值将是相应的User

现在,嵌套循环可以替换为单个循环:

List<User> getLoggedUsers() {
    Map<String,User> users = User.getUsers();
    List<User> onlineUsers = new ArrayList<>();
    for (String username : activeUsers.getUsers()) {
        User user = users.get(username);
        if(user != null) {
            onlineUsers.add(user);
        }
    }
    return onlineUsers;
}

在 Java 8 中,这可以简化为:

List<User> getLoggedUsers() {
    Map<String,User> users = User.getUsers();
    return activeUsers.getUsers()
                      .stream()
                      .map(users::get)
                      .filter(Objects::nonNull)
                      .collect(Collectors.toList());
}

我该怎么做:

@Autowired
private ActiveUsers activeUsers;
@RequestMapping(value = "/loggedUsers", method = RequestMethod.GET)
public @ResponseBody List<User> getLoggedUsers() {
    final List<User> users = User.getUsers();
    final List<User> activeUsersList = activeUsers.getUsers();
    return users.stream()
                .filter(user -> activeUsersList.contains(user))
                .colect(Collectors.toList());
}
使用从Java

8开始的流真的很好,而且不难理解。

使用以下代码行:

Set<User> onlineUsers = users.stream().filter(
    user -> activeUsers.getUsers().contains(user.getUserNmae())).collect(Collectors.toSet());

List<User> users转换为Map<String,User> users(其中键是用户名(。然后你可以跳过 1 for 循环并在 O(1( 时间进行 get。

Map<> myset = User.getUsers();

现在,您可以签入单个 for 循环并检查activeUsers是否包含 users

最新更新