6
votes

Mettre à jour une liste d'une autre liste

J'ai une liste d'utilisateurs dans un magasin local que je dois mettre à jour à partir d'une liste distante d'utilisateurs de temps en temps. Fondamentalement:

  1. Si un utilisateur distant existe déjà localement, mettez à jour ses champs. Li>
  2. Si un utilisateur distant n'existe pas déjà localement, ajoutez l'utilisateur. LI>
  3. Si un utilisateur local n'apparaît pas dans la liste distante, désactivez ou supprimez. LI>
  4. Si un utilisateur local apparaît également dans la liste distante, mettez à jour ses champs. (Identique à 1) li> ol>

    par exemple. Liste à distance: utilisateur (1, true), utilisateur (2, true), utilisateur (4, true), utilisateur (5, true) p>

    Liste locale: utilisateur (1, true), utilisateur (2 , faux), utilisateur (3, true), utilisateur (6, true) p>

    nouvelle liste locale: utilisateur (1, true), utilisateur (2, true), utilisateur (3, false), utilisateur (4, True), utilisateur (5, true), utilisateur (6, faux), p>

    juste un cas simple de synchronisation de la liste locale. Y a-t-il un meilleur moyen de le faire dans Pure Java que ce qui suit? Je me sens grossièrement en regardant mon propre code. P>

    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
            }
        }
    }
    


2 commentaires

1 et 4 doivent être faits qu'une seule fois, ils sont la même chose


Vous pouvez extraire des méthodes (comme update (utilisateur utilisateur) Intérieur utilisateur qui définirait les champs de utilisateur sur ceci ). Vous pouvez également utiliser java.util.collections.binginationSearch (liste, utilisateur) à l'intérieur des compréhensions.


3 Réponses :


1
votes

Vous pouvez utiliser list.indexof () code> au lieu d'itération via la liste:

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
    }
}


2 commentaires

Mais sans compréhension ou itération de la liste, comment puis-je obtenir les paramètres de mise à jour?


Variable localUser indéfini?



9
votes

Le meilleur moyen est de passer à une autre structure de données. Un mappe code> sera le meilleur, car il s'agit probablement des utilisateurs d'identification de manière unique. Votre choix de mappe code> peut être un hashmap code> (attendu O (1) code> pour les opérations de base) ou un treemap code > ( O (journal n) code>).

IMPORTANT: vous @override est égal (objet) code> sans @override hashcode () code> !! ! C'est dangereux fort>! Vous devriez toujours entrer dans l'habitude de remplacer ni ni les deux! (Voir: Remplacer les égaux et le hashcode en Java ) p>

Donc, disons que vous avez mappe user> et et plan localusers code>. p>

1.) Si un utilisateur distant existe déjà localement, mettez à jour ses champs.
4.) Si un utilisateur local apparaît également dans la liste distante, mettez à jour ses champs. frappe> (identique 1)
2.) Si un utilisateur distant n'existe pas déjà localement, ajoutez l'utilisateur. p> blockQquote>

Recherche si un utilisateur code> à partir de est dans code> est dans localusers code> peut être répondu dans o (1) Code> ou O (journal n) code> avec un simple contenant de la carte code> et obtenez code>. p>

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);
}


5 commentaires

Il n'est pas toujours possible de basculer entre Liste et définir . Cela dépend du modèle de domaine.


Vous pouvez toujours utiliser définir en tant qu'intermédiaire. Il est toujours plus rapide parce que c'est O (n) ou O (n journal n) comme s'y oppose à O (n ^ 2) .


Voir la ligne ci-dessus: local = localusers.get (distant); list.get seulement prend un index entier non obj.


@Langali, ce code est pour quand localusers et users est définit , pas list . Lisez toute la réponse: Je suggère un commutateur de structure de données si possible ou utilisez un intermédiaire.


Ok, j'ai réalisé que définir n'a pas de obtenez , donc je suis passé sur plan , ce qui a plus de sens de toute façon.



1
votes

Langali:

En supposant que l'ID identifie de manière unique un utilisateur, j'ai quelques suggestions pour vous:

  • Créez un utilisateur de classe.Key (une classe intérieure de votre classe d'utilisateurs) et déplacez le champ ID dans celui-ci. Rendre la finale. Remplacez la méthode HashCode et égale à la classe User.Key utilise simplement l'ID: xxx
    • Créez une carte pour contenir vos utilisateurs. XXX ;
    • Utilisez cette carte pour contenir vos utilisateurs, puis utilisez le Obtenir et Containte de contenant pour rechercher ce que vous recherchez.

      Le problème avec la liste.Contains est que, sur une arracheListe, il effectue une analyse complète du contenu de la liste. Si vous le faites pour chaque article d'une deuxième liste, votre performance est O (N ^ 2), ce qui signifie que lorsque vous doublez les éléments que vous multipliez par quatre temps requis pour exécuter votre méthode. Un hashmap a une performance de O (journal (n)), ce qui signifie que si vous êtes 1000 objets, le temps nécessaire à l'exécution est juste 10 fois plus lent (environ).


0 commentaires