java - 从另一个列表更新列表

标签 java collections list-comprehension

我在本地商店中有一个用户列表,我需要每隔一段时间从远程用户列表中更新一次。基本上:

  1. 如果本地已存在远程用户,请更新其字段。
  2. 如果本地不存在远程用户,请添加该用户。
  3. 如果本地用户没有出现在远程列表中,则停用或删除。
  4. 如果本地用户也出现在远程列表中,更新其字段。 (同1)

例如。 远程列表:User(1, true), User(2, true), User(4, true), User(5, true)

本地列表:User(1, true), User(2, false), User(3, true), User(6, true)

新本地列表:User(1, true), User(2, true), User(3, false), User(4, true), User(5, true), User(6, false),

只是同步本地列表的一个简单案例。有没有比以下方法更好的纯 Java 方法?看着我自己的代码,我觉得很恶心。

public class User {
    Integer id;
    String email;
    boolean active;

    //Getters and Setters.......

    public User(Integer id, String email, boolean active) {
        this.id = id;
        this.email = email;
        this.active = active;
    }

    @Override 
    public boolean equals(Object other) {
        boolean result = false;
        if (other instanceof User) {
            User that = (User) other;
            result = (this.getId() == that.getId());
        }
        return result;
    }

}




public static void main(String[] args) {

    //From 3rd party
    List<User> remoteUsers = getRemoteUsers();

    //From Local store
    List<User> localUsers =getLocalUsers();     

    for (User remoteUser : remoteUsers) {
        boolean found = false;
        for (User localUser : localUsers) {
            if (remoteUser.equals(localUser)) {
                found = true;
                localUser.setActive(remoteUser.isActive());
                localUser.setEmail(remoteUser.getEmail());
                //update
            } 
            break;
        }
        if (!found) {
            User user = new User(remoteUser.getId(), remoteUser.getEmail(), remoteUser.isActive());
            //Save
        }
    }

    for(User localUser : localUsers ) {
        boolean found = false;
        for(User remoteUser : remoteUsers) {
            if(localUser.equals(remoteUser)) {
                found = true;
                localUser.setActive(remoteUser.isActive());
                localUser.setEmail(remoteUser.getEmail());
                //Update
            }
            break;
        }
        if(!found) {
            localUser.setActive(false);
            // Deactivate
        }
    }
}

最佳答案

最好的方法是切换到不同的数据结构。 Map<Integer, User>将是最好的,因为大概用户具有唯一标识 ID。您的选择Map实现可以是 HashMap (预期 O(1) 用于基本操作)或 TreeMap (O(log N))。

重要提示:您 @Override equals(Object)没有@Override hashCode() !!!这很危险!您应该始终养成不覆盖任何一个或两者的习惯! (参见: Overriding equals and hashCode in Java )

那么,假设您有 Map<Integer, User> remoteUsersMap<Integer, User> localUsers .

1.) If a remote user already exists locally, update its fields.
4.) If a local user also appears in the remote list, update its fields. (same as 1)
2.) If a remote user doesn't already exist locally, add the user.

寻找一个User来自 remoteUserslocalUsers可以在O(1)中得到解答或 O(log N)用一个简单的 containsKeyget .

for (int id : remoteUsers.keys()) {
   User local;
   if (localUsers.containsKey(id)) {
      local = localUsers.get(id);
   else {
      localUsers.put(id, local = new User(id));
   }
   local.updateFrom(remoteUsers.get(id));
}

3.) If a local user doesn't appear in the remote list, deactivate or delete.

以下解决方案展示了这些更高级的数据结构的强大功能:

Set<Integer> toDeactivate = new TreeSet<Integer>();
toDeactivate.addAll(localUsers.keySet());
toDeactivate.removeAll(remoteUsers.keySet());

for (int id : toDeactivate) {
   User local = localUsers.get(id);
   local.deactivate();
   localUsers.remove(id);
}

此外,如果您遇到 List<User> 问题, 你仍然可以使用 Map<Integer, User>作为此处理的中间数据结构(基本上将 List<User> 转换为 Map<Integer, User> 然后返回 List<User> )。它仍然会更快,因为它是 O(N log N)O(N) , 与 O(N^2) 相比你现在拥有的。

如果您坚持只使用列表,那么您可能需要考虑将其设为 Collections.sort -ed 列表,所以你可以做 Collections.binarySearch在上面。您需要提供 Comparator<User> , 或制作 User implements Comparable<User> , 自然按 id 排序.这也将是 O(N log N) .

关于java - 从另一个列表更新列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2435773/

相关文章:

python - 使用这个 setitem 函数来克服列表理解限制会不会非常不符合 pythonic?

python - 将文件中的句子转换为列表中的单词标记

java - 使用Spring CachingConnectionFactory时什么时候适合缓存Consumers?

java - 静态实用方法 - 显式 NULL 检查与 @NonNull 与显式抛出

java - 如何重新排序以下列表数据

NavigableSet/Map 上的 Javadocs 和 jdk 不匹配?

java - 如何获取 Map<Long, Date> 中的最新日期?

java - Spring ws 和多个模式

java - 防止用户输入大于 int max 的值?

python - 使用列表理解删除字符串中的所有元音