Java 从另一个列表更新列表

Java 从另一个列表更新列表,java,collections,list-comprehension,Java,Collections,List Comprehension,我在本地存储中有一个用户列表,我需要每隔一段时间从远程用户列表中更新一次。基本上: 如果本地已存在远程用户,请更新其字段 如果远程用户在本地不存在,请添加该用户 如果本地用户未出现在远程列表中,请停用或删除 如果本地用户也出现在远程列表中,请更新其字段。(同1) 例如。 远程列表:用户(1,真)、用户(2,真)、用户(4,真)、用户(5,真) 本地列表:用户(1,真)、用户(2,假)、用户(3,真)、用户(6,真) 新的本地列表:用户(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
            }
        }
    }
    
    公共类用户{
    整数id;
    字符串电子邮件;
    布尔主动;
    //接受者和接受者。。。。。。。
    公共用户(整数id、字符串电子邮件、布尔活动){
    this.id=id;
    this.email=电子邮件;
    这个.active=active;
    }
    @凌驾
    公共布尔等于(对象其他){
    布尔结果=假;
    if(用户的其他实例){
    User that=(User)other;
    结果=(this.getId()==that.getId());
    }
    返回结果;
    }
    }
    公共静态void main(字符串[]args){
    //来自第三方
    List remoteUsers=getRemoteUsers();
    //从本地商店
    List localUsers=getLocalUsers();
    for(用户远程用户:远程用户){
    布尔值=false;
    for(用户localUser:localUsers){
    if(remoteUser.equals(localUser)){
    发现=真;
    localUser.setActive(remoteUser.isActive());
    localUser.setEmail(remoteUser.getEmail());
    //更新
    } 
    打破
    }
    如果(!找到){
    User User=新用户(remoteUser.getId(),remoteUser.getEmail(),remoteUser.isActive());
    //拯救
    }
    }
    for(用户localUser:localUsers){
    布尔值=false;
    for(用户远程用户:远程用户){
    if(localUser.equals(remoteUser)){
    发现=真;
    localUser.setActive(remoteUser.isActive());
    localUser.setEmail(remoteUser.getEmail());
    //更新
    }
    打破
    }
    如果(!找到){
    localUser.setActive(false);
    //停用
    }
    }
    }
    
    您可以使用
    List.indexOf()
    而不是遍历列表:

    for (User remoteUser : remoteUsers) {
        int index = localUsers.indexOf(remoteUser);
        if (index >= 0) {
            User localUser = localUsers.get(index);
            localUser.setActive(remoteUser.isActive());
            localUser.setEmail(remoteUser.getEmail());
            //update
        } else {
            User user = new User(remoteUser.getId(), remoteUser.getEmail(), remoteUser.isActive());
            //Save
        }
    }
    

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

    重要提示:您
    @Override equals(Object)
    没有
    @Override hashCode()
    !!!这是危险的!你应该养成一种习惯,既不凌驾于两者之上,也不凌驾于两者之上!(见:)

    那么,假设您有
    映射远程用户
    映射本地用户

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

    查找来自
    remoteUsers
    User
    是否在
    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.)如果本地用户未出现在远程列表中,请停用或删除

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

    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);
    }
    
    设置为deactivate=newtreeset();
    toDeactivate.addAll(localUsers.keySet());
    toDeactivate.removeAll(remoteUsers.keySet());
    for(int-id:toDeactivate){
    User local=localUsers.get(id);
    local.deactivate();
    localUsers.remove(id);
    }
    

    此外,如果您一直使用
    列表
    ,您仍然可以使用
    映射
    作为此处理的中间数据结构(基本上将
    列表
    转换为
    映射
    ,然后返回到
    列表
    )。它仍然会更快,因为它是
    O(N logn)
    O(N)
    ,而不是您现在拥有的
    O(N^2)

    如果您坚持只使用列表,那么您可能希望将其设置为
    集合.sort
    -ed列表,这样您就可以对其执行
    集合.binarySearch
    。您需要提供一个
    比较器
    ,或者让
    用户实现可比较的
    ,自然地按
    id
    排序。这也将是
    O(N log N)

    Langali:

    假设Id唯一标识用户,我有一些建议:

    • 创建一个类User.Key(用户类的内部类),并将id字段移到其中。最后决定。仅使用id重写User.Key类上的hashcode and equals方法:
    公共用户{ 最终私钥; …其他变量 公共静态类密钥{ 私有最终int id; 公钥(最终整数id){ } //hashcode(可以是id) //等于(如您所实施的) } }
    • 创建地图以容纳用户。地图 Map<User.Key, User>
    • 使用此地图保留您的用户,然后使用
      get
      containsKey
      方法查找您要查找的内容
    List.contains的问题是,在ArrayList上,它对列表内容执行完全扫描。如果您对第二个列表中的每一项都这样做,那么您的性能是O(n^ Map<User.Key, User>