我在本地商店中有一个用户列表,我需要每隔一段时间从远程用户列表中更新一次。基本上:
- 如果本地已存在远程用户,请更新其字段。
- 如果本地不存在远程用户,请添加该用户。
- 如果本地用户没有出现在远程列表中,则停用或删除。
- 如果本地用户也出现在远程列表中,更新其字段。 (同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> remoteUsers
和 Map<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
来自 remoteUsers
在localUsers
可以在O(1)
中得到解答或 O(log N)
用一个简单的 containsKey
和 get
.
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/