J'ai une grande carte de String-> Entier et je souhaite trouver les 5 valeurs les plus élevées sur la carte. Mon approche actuelle consiste à traduire la carte dans une liste de matrices d'objet paire (clé, de valeur), puis à trier à l'aide de collections.sort () avant de prendre le premier 5. Il est possible pour une clé de la mise à jour de sa valeur au cours de l'opération. . P>
Je pense que cette approche est acceptable unique filetée, mais si j'avais plusieurs threads qui déclenchent toutes les transpositions et trichent fréquemment, il ne semble pas très efficace. L'alternative semble être de conserver une liste distincte des 5 entrées les plus élevées et de la conserver à mises à jour lorsque des opérations pertinentes sur la carte ont lieu. P>
Pourrais-je avoir des suggestions / alternatives à l'optimisation de cela s'il vous plaît? Je suis heureux d'envisager différentes structures de données s'il y a un avantage. P>
merci! p>
7 Réponses :
Eh bien, pour trouver les 5 valeurs les plus élevées sur une carte, vous pouvez le faire dans Le moyen le plus simple est de simplement faire A Pour boucle via l'ensemble de saisie de la carte. p> O (n) code> temps où toute sorte est plus lente que celle-là.
Je pense que cette approche est acceptable unique filetée, mais si j'avais plusieurs threads qui déclenchent toutes les transpositions et trichent fréquemment, il ne semble pas très efficace. L'alternative semble être de conserver une liste distincte des 5 entrées les plus élevées et de la conserver à mises à jour lorsque des opérations pertinentes sur la carte ont lieu. P>
Il y a une approche entre ceux que vous pouvez prendre aussi bien. Lorsqu'un thread demande une "vue triée" de la carte, créez une copie de la carte, puis gérez le tri à ce sujet. p>
xxx pré> idéalement si vous avez un état (tel que cette carte) accessible par plusieurs threads, vous encapsulez l'état derrière une autre classe de sorte que chaque thread ne met pas à jour la carte. directement. p> blockquote>
Veuillez essayer une autre structure de données. Supposons qu'il y ait une classe nommée MyClass que ses attributs sont la clé (chaîne) et la valeur (int). MyClass, bien sûr, doit mettre en œuvre une interface comparable. Une autre approche consiste à créer une classe nommée MyClassComparator qui étend le comparateur. P>
La méthode de comparète (peu importe où elle est) doit être définie comme ceci: comparèteo (paramètres) { Valeur de retour2 - Value1; // décroissant } p>
Le reste est facile. Utilisation de la liste et d'invoquer la méthode des collections.sort (Paramètres) fera la partie de tri. P>
Je ne sais pas ce qui trie les collections d'algorithme.sort (paramètres) utilise. Mais si vous sentez que certaines données peuvent venir au fil du temps, vous aurez besoin d'une sorte d'insertion. Comme il est bon pour une donnée qui a presque trié et c'est en ligne . P>
Une autre fonction de l'API a la nécessité de récupérer une clé rapidement afin d'échanger une collection au lieu d'une carte blesser cette performance inacceptable comme la liste est grande. Cependant, votre idée est sonore - il n'y a aucune raison pour que je ne puisse pas mapper (clé -> composite (clé, valeur)) où le composite implémente comparable. Je pourrais alors juste dire des collections.sort (Carte.Values ()). Malheureusement, cela a toujours l'impact de la performance lorsque vous introduisez plusieurs threads à mesure que chaque thread pourrait une sorte de fusion (N (N log n)).
Vous pouvez utiliser deux cartes: et assurez-vous de toujours les garder en synchronisation (éventuellement envelopper les deux dans une autre classe responsable de mettre, d'obtenir, etc.). Pour les valeurs les plus élevées, utilisez byvalue.navigablekeyset (). Descendickatorator () Code>. P> P>
J'aime vraiment ça, mais de la mémoire ne ferait pas que cela nécessite que toutes les valeurs sont uniques. Il est peu probable que cela soit le cas dans mon domaine, la carte de Byvalue serait probablement corrompue.
Bon point, j'ai modifié byvalue code> pour contenir tous les noms d'une valeur donnée.
Si des modifications sont rares, j'étais implémenter quelque chose triétébyvalhashmap
linkedhashmap code>) qui maintient les entrées commandées par valeur. P>
Je créerais une méthode comme: tirer parti de collections.max () code> et
collections.singleton () code> code> < / p> p>
Ceci est O (n), mais dans la pratique fonctionne assez lentement par rapport à d'autres méthodes.
Il y a deux façons de le faire facilement: p>
n code> éléments que vous voulez d'it. li>
- Itérate via la carte et mettre à jour une liste de
n code> les valeurs les plus élevées en utilisant chaque entrée. LI>
ol>
Si vous souhaitez rétrécir un inconnu ou un grand nombre de valeurs les plus élevées, la première méthode est la voie à suivre. Si vous avez une petite quantité de valeurs fixe pour récupérer, la seconde pourrait être plus facile à comprendre pour certains programmeurs.
Personnellement, je préfère la première méthode. P>
Deux questions: 1) Pourquoi avoir une carte? Avez-vous besoin de rechercher des valeurs pour des clés données? 2) Avez-vous également besoin de connaître les clés des 5 valeurs les plus élevées?
@pgras - Oui, une autre fonction de l'API est de recevoir une clé et de renvoyer la valeur actuelle afin que une carte soit un bon point de départ. Nous avons besoin de connaître les clés pour les valeurs les plus élevées, c'est pourquoi j'ai été forcé d'utiliser un objet paire et non seulement créer une liste d'entiers.
Pouvez-vous spécifier les exigences de l'heure d'exécution exactement avez-vous à l'esprit? Votre actuel
gethighestfive code> est
O (n log n) code>, tout en modifiant la carte avec
lookup code>,
insérer code> et
Supprimer code> est
O (journal n) code> chacun. Voulez-vous obtenir
gethaghestfive code> vers le bas de
o (1) code> tout en préservant les autres heures d'exécution? Qu'est-ce que cela a à voir avec plusieurs threads, voulez-vous parallementer
gethighestfive code>?