从另一个列表更新列表

Lan*_*ali 3 java collections list-comprehension

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

  1. 如果远程用户已在本地存在,请更新其字段.
  2. 如果本地尚不存在远程用户,请添加该用户.
  3. 如果本地用户未出现在远程列表中,请取消激活或删除.
  4. 如果本地用户也出现在远程列表中,请更新其字段.(与1相同)

例如.远程列表:用户(1,真),用户(2,真),用户(4,真),用户(5,真)

本地列表:用户(1,真),用户(2,假),用户(3,真),用户(6,真)

新的本地列表:用户(1,真),用户(2,真),用户(3,假),用户(4,真),用户(5,真),用户(6,假),

只是一个同步本地列表的简单案例.有没有更好的方法在纯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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

pol*_*nts 7

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

重要提示:你@Override equals(Object)没有@Override hashCode()!!! 这很危险!你应该总是养成不要两者兼顾的习惯!(请参阅: 在Java中覆盖equals和hashCode )

所以,让我们说你有Map<Integer, User> remoteUsersMap<Integer, User> localUsers.

1.)如果远程用户已在本地存在,请更新其字段.
4.)如果本地用户也出现在远程列表中,请更新其字段.(与1相同)
2.)如果本地尚不存在远程用户,请添加用户.

如果发现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));
}
Run Code Online (Sandbox Code Playgroud)

3.)如果本地用户未出现在远程列表中,则取消激活或删除.

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

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);
}
Run Code Online (Sandbox Code Playgroud)

此外,如果您坚持使用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).