Comment communiquer que l'ordre d'insertion est important dans une carte?

24

Je récupère un ensemble de tuples dans la base de données et je le mets dans une carte. La requête de base de données est coûteuse.

Il n'y a pas d' ordre naturel évident des éléments dans la carte, mais l' ordre d'insertion est néanmoins important. Le tri de la carte serait une opération lourde, donc je veux éviter de le faire, étant donné que le résultat de la requête est déjà trié comme je le veux. Par conséquent, je stocke simplement le résultat de la requête dans un LinkedHashMapet retourne la carte à partir d'une méthode DAO:

public LinkedHashMap<Key, Value> fetchData()

J'ai une méthode processDataqui devrait faire un certain traitement sur la carte - modifier certaines valeurs, ajouter de nouvelles clés / valeurs. Il est défini comme

public void processData(LinkedHashMap<Key, Value> data) {...}

Cependant, plusieurs linters (Sonar, etc.) se plaignent que le type de «données» devrait être une interface telle que «Map» plutôt que l'implémentation «LinkedHashMap» ( calmar S1319 ).
Donc, fondamentalement, il dit que j'aurais dû

public void processData(Map<Key, Value> data) {...}

Mais je veux que la signature de la méthode dise que l' ordre des cartes est important - cela compte pour l'algorithme processData- afin que ma méthode ne soit pas transmise à n'importe quelle carte aléatoire.

Je ne veux pas l'utiliser SortedMap, car il (à partir du javadoc dejava.util.SortedMap ) "est ordonné selon l' ordre naturel de ses clés, ou par un comparateur généralement fourni au moment de la création de la carte triée".

Mes clés n'ont pas d' ordre naturel , et la création d'un comparateur pour ne rien faire semble verbeuse.

Et je voudrais quand même que ce soit une carte, pour en profiter putpour éviter les clés en double, etc. Sinon, cela dataaurait pu être a List<Map.Entry<Key, Value>>.

Alors, comment dire que ma méthode veut une carte déjà triée ? Malheureusement, il n'y a pas d' java.util.LinkedMapinterface, ou je l'aurais utilisé.

Vidar S. Ramdal
la source

Réponses:

56

Alors utilisez LinkedHashMap.

Oui , vous devez utiliser Mapune implémentation spécifique dans la mesure du possible, et oui , c'est la meilleure pratique.

Cela dit, il s'agit d'une situation étrangement spécifique où la mise en œuvre des Mapquestions est réellement importante. Ce ne sera pas vrai pour 99,9% des cas dans votre code lorsque vous utilisez Map, et pourtant vous êtes ici, dans cette situation de 0,1%. Sonar ne peut pas le savoir et Sonar vous dit simplement d'éviter d'utiliser l'implémentation spécifique car elle serait correcte dans la plupart des cas.

Je dirais que si vous pouvez justifier l'utilisation d'une implémentation spécifique, n'essayez pas de mettre du rouge à lèvres sur un cochon. Vous avez besoin d'un LinkedHashMap, pas d'un Map.

Cela dit, si vous êtes nouveau dans la programmation et tombez sur cette réponse, ne pensez pas que cela vous permet d'aller à l'encontre des meilleures pratiques, car ce n'est pas le cas. Mais lorsque le remplacement d'une implémentation par une autre n'est pas acceptable, la seule chose que vous pouvez faire est d'utiliser cette implémentation spécifique et d'être damné envers Sonar.

Neil
la source
1
Approche pragmatique, que j'aime.
Vidar S. Ramdal,
20
Je suis presque entièrement d'accord avec la réponse. Je dirais simplement que vous n'êtes pas damné envers Sonar. Vous pouvez toujours le configurer pour ignorer cette erreur / avertissement particulier. Voir stackoverflow.com/questions/10971968/…
Vladimir Stokic
11
if you are new to programming and stumble upon this answer, don't think this allows you to go against best practice because it doesn't.- Bon conseil, s'il existait une "meilleure pratique". Un meilleur conseil: apprenez à prendre les bonnes décisions. Suivez la pratique si cela a du sens, mais laissez les outils et les autorités guider votre processus de réflexion, pas le dicter.
Robert Harvey
13
Remarque: lorsque le sondeur vous signale quelque chose, vous pouvez le fermer comme "ne sera pas résolu" et laisser une note expliquant pourquoi vous ne le ferez pas. En tant que tel, non seulement le sonar cessera de vous déranger, mais vous saurez pourquoi vous avez fait cela.
Walfrat
2
Je pense que l'aspect qui en fait une exception au principe général est que LinkedHashMap a un contrat spécifique à cette implémentation et qui n'est exprimé dans aucune interface. Ce n'est pas le cas habituel. Donc, la seule façon d'exprimer la dépendance à l'égard de ce contrat est d'utiliser le type de mise en œuvre.
Dana
21

Vous vous battez contre trois choses:

La première est la bibliothèque de conteneurs de Java. Rien dans sa taxonomie ne vous permet de déterminer si la classe itère ou non dans un ordre prévisible. Aucune IteratesInInsertedOrderMapinterface ne peut être implémentée LinkedHashMap, ce qui rend impossible la vérification de type (et l'utilisation d'implémentations alternatives qui se comportent de la même manière). C'est probablement par conception, car l'esprit de celui-ci est que vous êtes vraiment censé pouvoir traiter des objets qui se comportent comme l'abstrait Map.

Deuxièmement, nous croyons que ce que dit votre interlocuteur doit être traité comme un évangile et qu'ignorer tout ce qu'il dit est mauvais. Contrairement à ce qui passe pour une bonne pratique ces jours-ci, les avertissements de linter ne sont pas censés être des barrières pour qualifier votre code de bon. Ils sont invités à raisonner sur le code que vous avez écrit et à utiliser votre expérience et votre jugement pour déterminer si l'avertissement est justifié ou non. Les avertissements injustifiés sont la raison pour laquelle presque tous les outils d'analyse statique fournissent un mécanisme pour leur dire que vous avez examiné le code, que vous pensez que ce que vous faites est correct et qu'ils ne devraient pas s'en plaindre à l'avenir.

Troisièmement, et c'est probablement la viande de celui-ci, LinkedHashMappeut être le mauvais outil pour le travail. Les cartes sont destinées à un accès aléatoire et non ordonné. Si vous processData()parcourez simplement les enregistrements dans l'ordre et n'avez pas besoin de trouver d'autres enregistrements par clé, vous forcez une implémentation spécifique Mapà faire le travail d'un List. D'un autre côté, si vous avez besoin des deux, LinkedHashMapc'est le bon outil car il est connu pour faire ce que vous voulez et vous êtes plus que justifié de l'exiger.

Blrfl
la source
2
"LinkedHashMap n'est peut-être pas le bon outil pour le travail". Oui peut-être. Quand je dis que j'ai besoin d'un OrderedMap, je pourrais tout aussi bien dire UniqueList. Tant qu'il s'agit d'une sorte de collection avec un ordre d'itération défini, qui écrase les doublons lors de l'insertion.
Vidar S. Ramdal
2
@ VidarS.Ramdal La requête de base de données serait l'endroit idéal pour éliminer les doublons. Si votre base de données ne peut pas le faire, vous pouvez toujours conserver temporairement Setles clés pendant que vous créez la liste a pour les repérer.
Blrfl
Oh, je vois que j'ai semé la confusion. Oui, le résultat de la requête de base de données ne contient pas de doublons. Mais processDatamodifie la carte, en remplaçant certaines valeurs, en introduisant de nouvelles clés / valeurs. Il processDatapourrait donc introduire des doublons s'il fonctionnait sur autre chose qu'un Map.
Vidar S. Ramdal
7
@ VidarS.Ramdal: Il semble que vous ayez besoin d'écrire votre propre UniqueList(ou OrderedUniqueList) et de l'utiliser. C'est assez facile et rend votre utilisation prévue plus claire.
TMN
2
@TMN Oui, j'ai commencé à penser dans ce sens. Si vous souhaitez publier votre suggestion en tant que réponse, elle recevra certainement mon vote positif.
Vidar S. Ramdal
15

Si tout ce que vous obtenez LinkedHashMapest la possibilité d'écraser les doublons, mais que vous l'utilisez vraiment en tant que List, alors je suggère qu'il est préférable de communiquer cette utilisation avec votre propre Listimplémentation personnalisée . Vous pouvez la baser sur une classe de collections Java existante et simplement remplacer toutes les méthodes addet removepour mettre à jour votre magasin de sauvegarde et garder une trace de la clé pour garantir l'unicité. En lui donnant un nom distinctif, il ProcessingListsera clair que les arguments présentés à votre processDataméthode doivent être traités d'une manière particulière.

TMN
la source
5
Cela peut être une bonne idée de toute façon. Heck, vous pouvez même avoir un fichier d'une ligne qui crée ProcessingListcomme un alias pour LinkedHashMap- vous pouvez toujours décider de le remplacer par quelque chose d'autre plus tard, tant que vous gardez l'interface publique intacte.
CompuChip
11

Je vous entends dire "J'ai une partie de mon système qui produit un LinkedHashMap, et dans une autre partie de mon système, je dois accepter uniquement les objets LinkedHashMap qui ont été produits par la première partie, car ceux produits par un autre processus ont gagné" t fonctionne correctement. "

Cela me fait penser que le problème ici est en fait que vous essayez d'utiliser LinkedHashMap car il correspond principalement aux données que vous recherchez, mais en fait, il ne peut pas être remplacé par une autre instance que celles que vous créez. Ce que vous voulez réellement faire, c'est créer votre propre interface / classe qui est ce que votre première partie crée et votre deuxième partie consomme. Il peut envelopper le "vrai" LinkedHashMap, et fournir un getter de carte ou implémenter l'interface de carte.

Ceci est un peu différent de la réponse de CandiedOrange, en ce que je recommanderais d'encapsuler la vraie carte (et de lui déléguer des appels si nécessaire) plutôt que de l'étendre. C'est parfois une de ces guerres sacrées de style, mais il me semble que ce n'est pas "une carte avec des trucs supplémentaires", c'est "mon sac d'informations utiles sur l'état, que je peux représenter en interne avec une carte".

Si vous aviez deux variables que vous aviez besoin de faire circuler comme ceci, vous auriez probablement fait une classe pour elle sans y penser beaucoup. Mais parfois, il est utile d'avoir une classe même si ce n'est qu'une variable membre, simplement parce que c'est logiquement la même chose, pas une "valeur" mais "le résultat de mon opération avec lequel je dois faire des choses plus tard".


la source
Je aime cette façon de penser - je suis là :) MyBagOfUsefulInformationaurait besoin d' une méthode (ou le constructeur) pour le remplir: MyBagOfUsefulInformation.populate(SomeType data). Mais datadevrait être le résultat de la requête triée. Alors, que serait-ce SomeTypesinon LinkedHashMap? Je ne suis pas sûr de pouvoir battre ce Catch 22.
Vidar S. Ramdal
Pourquoi ne peut pas MyBagOfUsefulInformationêtre créé par le DAO ou quoi que ce soit qui génère les données dans votre système? Pourquoi avez-vous besoin d'exposer la carte sous-jacente au reste de votre code en dehors du producteur et du consommateur du sac?
Selon votre architecture, vous pourrez peut-être utiliser un constructeur privé / protégé / package uniquement pour faire en sorte que l'objet ne puisse être créé que par le producteur que vous souhaitez. Ou vous devrez peut-être simplement le faire comme une convention, qu'il ne peut être créé que par la bonne "usine".
Oui, j'ai fini par faire quelque chose d'un peu similaire, en passant MyBagOfUsefulInformationcomme paramètre à la méthode DAO: softwareengineering.stackexchange.com/a/360079/52573
Vidar S. Ramdal
4

LinkedHashMap est la seule carte java qui possède la fonction d'ordre d'insertion que vous recherchez. Donc, écarter le principe d'inversion de dépendance est tentant et peut-être même pratique. Mais d'abord, réfléchissez à ce qu'il faudrait pour le suivre. Voici ce que SOLID vous demanderait de faire.

Remarque: remplacez le nom Ramdalpar un nom descriptif qui indique que le consommateur de cette interface est le propriétaire de cette interface. Ce qui en fait l'autorité qui décide si l'ordre d'insertion est important. Si vous appelez simplement cela, InsertionOrderMapvous avez vraiment manqué le point.

public interface Ramdal {
    //ISP asks for just the methods that processData() actually uses.
    ...
}

public class RamdalLinkedHashMap extends LinkedHashMap implements Ramdal{} 

Ramdal<Key, Value> ramdal = new RamdalLinkedHashMap<>();

ramdal.put(key1, value1);
ramdal.put(key2, value2);

processData(ramdal);

Est-ce un gros design d'avance? Cela dépend peut-être de la probabilité que vous pensiez avoir besoin d'une implémentation LinkedHashMap. Mais si vous ne suivez pas DIP uniquement parce que ce serait une énorme douleur, je ne pense pas que la plaque de la chaudière soit plus douloureuse que cela. C'est le modèle que j'utilise lorsque je souhaite que le code intouchable implémente une interface qu'il ne fait pas. La partie la plus douloureuse est vraiment de penser à de bons noms.

candied_orange
la source
2
J'aime la dénomination!
Vidar S. Ramdal,
1

Merci pour beaucoup de bonnes suggestions et de matière à réflexion.

J'ai fini par étendre la création d'une nouvelle classe de carte, en créant processDataune méthode d'instance:

class DataMap extends LinkedHashMap<Key, Value> {

   processData();

}

Ensuite, j'ai refactorisé la méthode DAO afin qu'elle ne renvoie pas de carte, mais prend à la place une targetcarte en paramètre:

public void fetchData(Map<Key, Value> target) {
  ...
  // for each result row
  target.put(key, value);
}

Donc, remplir DataMapet traiter les données est maintenant un processus en deux étapes, ce qui est bien, car il existe d'autres variables qui font partie de l'algorithme, qui viennent d'autres endroits.

public DataMap fetchDataMap() {
  var dataMap = new DataMap();
  dao.fetchData(dataMap);
  return dataMap;
}

Cela permet à mon implémentation Map de contrôler la façon dont les entrées y sont insérées, et masque les exigences de classement - c'est maintenant un détail d'implémentation de DataMap.

Vidar S. Ramdal
la source
0

Si vous souhaitez indiquer que la structure de données que vous avez utilisée existe pour une raison, ajoutez un commentaire au-dessus de la signature de la méthode. Si un autre développeur à l'avenir rencontre cette ligne de code et remarque un avertissement d'outil, il peut également remarquer le commentaire et s'abstenir de "résoudre" le problème. S'il n'y a pas de commentaire, rien ne les empêchera de changer la signature.

Supprimer les avertissements est inférieur à commenter à mon avis, car la suppression elle-même n'indique pas la raison pour laquelle l'avertissement a été supprimé. Une combinaison de suppression d'avertissement et de commentaire conviendra également.

Kapol
la source
0

Alors, laissez-moi essayer de comprendre votre contexte ici:

... l'ordre d'insertion est important ... Trier la carte serait une opération lourde ...

... le résultat de la requête est déjà trié comme je le veux

Maintenant, ce que vous faites actuellement:

J'aller chercher un ensemble de tuples de la base de données, et le mettre dans une carte ...

Et voici votre code actuel:

public void processData(LinkedHashMap<Key, Value> data) {...}

Ma suggestion est de faire ce qui suit:

  • Utilisez l' injection de dépendances et injectez du MyTupleRepository dans la méthode de traitement (MyTupleRepository est une interface implémentée par des objets qui récupèrent vos objets tuple, généralement à partir de DB);
  • en interne à la méthode de traitement, placez les données du référentiel (alias DB, qui renvoie déjà les données ordonnées) dans la collection LinkedHashMap spécifique, car il s'agit de détails internes de l'algorithme de traitement (car cela dépend de la façon dont les données sont organisées dans la structure de données );
  • Notez que c'est à peu près ce que vous faites déjà, mais dans ce cas, cela se ferait dans le cadre de la méthode de traitement. Votre référentiel est instancié ailleurs (vous avez déjà une classe qui renvoie des données, c'est le référentiel dans cet exemple)

Exemple de code

public interface MyTupleRepository {
    Collection<MyTuple> GetAll();
}

//Concrete implementation of data access object, that retrieves 
//your tuples from DB; this data is already ordered by the query
public class DbMyTupleRepository implements MyTupleRepository { }

//Injects some abstraction of repository into the processing method,
//but make it clear that some exception might be thrown if data is not
//arranged in some specific way you need
public void processData(MyTupleRepository tupleRepo) throws DataNotOrderedException {

    LinkedHashMap<Key, Value> data = new LinkedHashMap<Key, Value>();

    //Represents the query to DB, that already returns ordered data
    Collection<MyTuple> myTuples = tupleRepo.GetAll();

    //Optional: this would throw some exception if data is not ordered 
    Validate(myTuples);

    for (MyTupleData t : myTuples) {
        data.put(t.key, t.value);
    }

    //Perform the processing using LinkedHashMap...
    ...
}

Je suppose que cela éliminerait l'avertissement Sonar et spécifierait également dans la signature la disposition spécifique des données requises par la méthode de traitement.

Emerson Cardoso
la source
Hmm, mais comment le référentiel serait-il instancié? Cela ne déplacerait-il pas simplement le problème ailleurs (vers l'endroit où il MyTupleRepositoryest créé?)
Vidar S. Ramdal
Je pense que je vais rencontrer le même problème qu'avec la réponse de Peter Cooper .
Vidar S. Ramdal,
Ma suggestion consiste à appliquer le principe de l'injection de dépendance; dans cet exemple; MyTupleRepository est une interface qui définit la capacité de récupérer les tuples que vous avez mentionnés (qui interroge DB). Ici, vous injectez cet objet dans la méthode de traitement. Vous avez déjà une classe qui renvoie les données; cela l'abstrait uniquement dans une interface, et vous injectez l'objet dans la méthode 'processData', qui utilise en interne le LinkedHashMap car cela fait intrinsèquement partie du traitement.
Emerson Cardoso
J'ai édité ma réponse, essayant d'être plus clair sur ce que je suggère.
Emerson Cardoso
-1

Cette question est en fait un tas de problèmes avec votre modèle de données regroupé en un seul. Vous devez commencer à les démêler, un à la fois. Des solutions plus naturelles et intuitives disparaissent lorsque vous essayez de simplifier chaque pièce du puzzle.

Problème 1: vous ne pouvez pas dépendre de l'ordre DB

Vos descriptions du tri de vos données ne sont pas claires.

  • Le plus gros problème potentiel est que vous ne spécifiez pas de tri explicite dans votre base de données, via une ORDER BYclause. Si ce n'est pas le cas, car cela semble trop cher, votre programme a un bug . Les bases de données sont autorisées à renvoyer les résultats dans n'importe quel ordre si vous n'en spécifiez pas; vous ne pouvez pas en dépendre par coïncidence en renvoyant des données dans l'ordre simplement parce que vous avez exécuté la requête plusieurs fois et que cela ressemble à cela. L'ordre peut changer car les lignes sont réorganisées sur le disque, ou certaines sont supprimées et de nouvelles prennent leur place, ou un index est ajouté. Vous devez spécifier une ORDER BYclause quelconque. La vitesse ne vaut rien sans correction.
  • Il n'est pas clair non plus ce que vous entendez par ordre d'insertion. Si vous parlez de la base de données elle-même, vous devez avoir une colonne qui suit réellement cela, et elle doit être incluse dans votre ORDER BYclause. Sinon, vous avez des bugs. Si une telle colonne n'existe pas encore, vous devez en ajouter une. Les options typiques pour des colonnes comme celle-ci seraient une colonne d'horodatage d'insertion ou une clé d'incrémentation automatique. La clé d'incrémentation automatique est plus fiable.

Problème 2: Rendre le tri en mémoire efficace

Une fois que vous assurez - vous qu'il est garanti à retourner les données dans l'ordre que vous attendez, vous pouvez tirer parti de ce fait pour faire en mémoire trie beaucoup plus efficace. Ajoutez simplement une colonne row_number()oudense_rank() (ou l'équivalent de votre base de données) à l'ensemble de résultats de votre requête. Maintenant, chaque ligne a un index qui vous donnera une indication directe de ce que l'ordre est censé être, et vous pouvez trier par ceci en mémoire trivialement. Assurez-vous simplement de donner à l'index un nom significatif (comme sortedBySomethingIndex).

Alto. Désormais, vous n'avez plus à dépendre de l'ordre du jeu de résultats de la base de données.

Problème 3: Avez-vous même besoin de faire ce traitement en code?

SQL est en fait vraiment puissant. C'est un langage déclaratif incroyable qui vous permet de faire beaucoup de transformations et d'agrégations sur vos données. De nos jours, la plupart des bases de données prennent même en charge les opérations entre lignes. On les appelle des fonctions de fenêtre ou d'analyse:

Avez-vous même besoin de mettre vos données en mémoire comme ça? Ou pourriez-vous faire tout le travail dans la requête SQL en utilisant des fonctions de fenêtre? Si vous pouvez faire tout (ou peut-être même juste une partie importante) du travail dans la base de données, fantastique! Votre problème de code disparaît (ou devient beaucoup plus simple)!

Problème 4: tu fais quoi à ça data?

En supposant que vous ne pouvez pas tout faire dans la base de données, permettez-moi de clarifier les choses. Vous prenez les données sous forme de carte (qui est basée sur des éléments que vous ne souhaitez pas trier), puis vous les itérez dans l' ordre d'insertion et modifiez la carte en place en remplaçant la valeur de certaines clés et en ajoutant les nouvelles?

Je suis désolé, mais qu'est-ce que c'est que ça?

Les appelants ne devraient pas avoir à se soucier de tout cela . Le système que vous avez créé est extrêmement fragile. Il suffit d'une seule erreur stupide (peut-être même faite par vous-même, comme nous l'avons tous fait) pour effectuer un petit changement erroné et le tout s'effondre comme un jeu de cartes.

Voici peut-être une meilleure idée:

  • Demandez à votre fonction d'accepter a List.
  • Il existe plusieurs façons de gérer le problème de commande.
    1. Appliquer l'échec rapide. Lance une erreur si la liste n'est pas dans l'ordre requis par la fonction. (Remarque: vous pouvez utiliser l'index de tri du problème 2 pour savoir s'il l'est.)
    2. Créez vous-même une copie triée (à nouveau en utilisant l'index du problème 2).
    3. Trouvez un moyen de construire la carte elle-même dans l'ordre.
  • Construisez la carte dont vous avez besoin en interne pour la fonction, afin que l'appelant n'ait pas à s'en soucier.
  • Maintenant, répétez ce que vous avez dans l'ordre et faites ce que vous avez à faire.
  • Renvoyer la carte ou la transformer en une valeur de retour appropriée

Une variante possible pourrait être de construire une représentation triée, puis de créer une carte de clé à indexer . Cela vous permettrait de modifier votre copie triée en place, sans créer accidentellement des doublons.

Ou peut-être que cela a plus de sens: se débarrasser du dataparamètre et faire processDataréellement récupérer ses propres données. Vous pouvez alors documenter que vous faites cela car cela a des exigences très spécifiques sur la façon dont les données sont récupérées. En d'autres termes, faites en sorte que la fonction soit propriétaire de l'intégralité du processus, et pas seulement d'une partie de celui-ci; les interdépendances sont trop fortes pour diviser la logique en petits morceaux. (Modifiez le nom de la fonction dans le processus.)

Peut-être que cela ne fonctionnera pas pour votre situation. Je ne sais pas sans tous les détails du problème. Mais je connais un design fragile et déroutant quand j'en entends un.

Sommaire

Je pense que le problème ici est finalement que le diable est dans les détails. Lorsque je commence à rencontrer des problèmes comme celui-ci, c'est généralement parce que j'ai une représentation inappropriée de mes données pour le problème que j'essaie de résoudre. La meilleure solution est de trouver une meilleure représentation , puis mon problème devient simple (peut-être pas facile, mais simple) à résoudre.

Trouvez quelqu'un qui obtient ce point: votre travail consiste à réduire votre problème à un ensemble de problèmes simples et directs. Ensuite, vous pouvez créer du code robuste et intuitif. Parlez-leur. Un bon code et une bonne conception vous font penser que n'importe quel idiot aurait pu les imaginer, car ils sont simples et directs. Peut-être y a-t-il un développeur senior qui a cet état d'esprit auquel vous pouvez parler.

jpmc26
la source
"Que voulez-vous dire qu'il n'y a pas d'ordre naturel mais que l'ordre d'insertion est important? Êtes-vous en train de dire que l'ordre des données a été inséré dans la table DB, mais vous n'avez pas de colonne qui puisse vous dire dans quel ordre les choses ont été insérées?" - la question indique ceci: "Le tri de la carte serait une opération lourde, donc je veux éviter de faire cela, étant donné que le résultat de la requête est déjà trié". Clairement qu'il existe des moyens est un ordre défini calculable aux données, car il serait autrement impossible de tri plutôt que lourd, mais cet ordre défini est différent de l'ordre naturel des clés.
Jules
2
En d'autres termes, OP travaille sur les résultats d'une requête comme select key, value from table where ... order by othercolumnet doit maintenir l'ordre dans leur traitement. L' ordre d'insertion auquel ils se réfèrent est l' ordre d'insertion dans leur carte , défini par l'ordre utilisé dans leur requête, et non l' ordre d'insertion dans la base de données . Cela est rendu clair par leur utilisation de LinkedHashMap, qui est une structure de données qui a les caractéristiques à la fois de a Mapet de a Listde paires clé-valeur.
Jules
@Jules Je vais nettoyer un peu cette section, merci. (Je me souvenais en fait de l'avoir lu, mais quand je vérifiais les choses pendant que j'écrivais la question, je ne pouvais pas la trouver. Lol. Je me suis trop mis dans les mauvaises herbes.) requête et si elles ont un tri explicite ou non. Ils disent également que «l'ordre d'insertion est important». Le fait est que même si le tri est lourd, vous ne pouvez pas compter sur la base de données pour simplement classer les choses par magie correctement si vous ne le lui dites pas explicitement. Et si vous êtes en train de faire dans le DB, vous pouvez utiliser un « index » pour le rendre efficace dans le code.
jpmc26
* écrit la réponse (Je pense que je devrais aller me coucher bientôt.)
jpmc26
Oui, @Jules a raison. Il y a une order byclause dans la requête, mais elle n'est pas triviale ( pas seulement order by column), donc je veux éviter de réimplémenter le tri en Java. Bien que SQL soit puissant (et nous parlons ici d'une base de données Oracle 11g), la nature de l' processDataalgorithme facilite son expression en Java. Et oui, "ordre d'insertion" signifie " ordre d'insertion de carte ", c'est-à-dire l'ordre des résultats de la requête.
Vidar S. Ramdal,