Implémentation d'une file d'attente FIFO à longueur fixe en Java Lorsque vous travaillez avec des données de séries temporelles, il est souvent nécessaire de calculer des sommes de nombres consécutifs pour un intervalle de temps prédéterminé. Imaginez, par exemple, le calcul d'une moyenne mobile avec une taille fixe. Let's regarder une série très simplement. En supposant une moyenne mobile de la longueur 4, on obtient le tableau suivant: La formule pour une moyenne mobile de longueur 4 est donc: MA t (Somme de tous les éléments de t-3 à t) 4 Comment appliquer efficacement ce code Java Le problème est que nous devons calculer la somme dans la formule pour chaque moyenne mobile. Bien sûr, il est toujours possible de répéter sur tous les nombres dans le calendrier actuel pour le faire, mais cela est inutilement lent. Au lieu de cela, nous pouvons simplement soustraire le dernier élément de l'intervalle de temps et ajouter le plus récent à Sum. De cette façon, nous pouvons économiser un nombre important de calculs inutiles. Nous devons toutefois garder une trace de ce qui est réellement l'ancien et les nouveaux éléments. Nous devons stocker ces numéros quelque part. Une structure de données appropriée serait une file d'attente de nombres premier-entré-premier-sorti (FIFO). Mais comment une file d'attente FIFO peut-elle être implémentée dans un langage de programmation (non fonctionnel) tel que Java La première idée consiste généralement à utiliser une implémentation basée sur un tableau et à déplacer la position des éléments dans le tableau en créant Le tableau. Dans l'exemple ci-dessus, nous devrions créer un nouveau tableau cinq fois, une fois pour chaque nouvelle somme étant calculée. Ceci est bien sûr très inefficace, car la création d'un tableau en mémoire est relativement lente. Les implémentations basées sur des classes telles que java. util. ArrayList ou java. util. Vector sont déjà bien meilleures, car elles reposent en interne sur des tableaux et des indices plus longs. Cependant, ce n'est pas la meilleure solution, car une fois que les indices internes se déplacent en dehors des limites du tableau interne, une nouvelle copie du tableau interne doit être créée. Une alternative typique pour implémenter des files d'attente FIFO est donc en utilisant une liste liée: L'avantage est évident, pas plus de copier ou de recréer des tableaux en mémoire. Tout ce que nous avons à faire est de manipuler quelques pointeurs. Bien sûr, nous perdons l'avantage d'évaluer directement un élément dans la file d'attente par index, mais pour notre but - le calcul des moyennes mobiles - c'est quelque chose que nous ne voulons pas faire de toute façon. Hier, je me suis soudainement rendu compte qu'il y avait une alternative encore meilleure si la longueur de la file d'attente était fixe (comme dans notre exemple). Nous pouvons effectivement utiliser une bague. Ajouter un nouveau numéro à la file d'attente et abandonner le plus ancien est le même que remplacer simplement l'élément le plus ancien de cet anneau par un nouveau. En interne, nous pouvons à nouveau utiliser un tableau d'une longueur fixe en combinaison avec un index tournant. C'est ainsi que le code ressemble en Java. Commençons par créer notre propre interface de file d'attente: Cette interface s'écarte un peu de celle fournie dans les bibliothèques Java, mais cela n'a aucune importance pour l'instant. Ensuite, la mise en œuvre de notre file d'attente: La file d'attente quotrollsquot à travers l'anneau. L'ajout d'un nouvel élément à la tête de la file supprime automatiquement l'élément le plus ancien de la file d'attente - aucune copie des tableaux ou réinitialisation des références d'objet requises. Contrairement aux listes liées, nous pouvons réellement accéder à chaque élément du cycle directement avec la méthode get. Enfin, nous pouvons créer une sous-classe de notre objet de file d'attente qui va gracieusement rouler comme de nouvelles valeurs sont ajoutées dans le queuering. Nous pouvons utiliser la classe maintenant. La longueur de la moyenne mobile est initialement fixée à travers la longueur du tableau donné à son constructeur. Je dois garder une trace des 7 derniers jours de travail dans une boucle de lecture de fichier plat. Il est utilisé pour mesurer la fatigueabilité des listes de travail. En ce moment j'ai quelque chose qui fonctionne, mais il semble plutôt verbeux et je ne sais pas si theres un modèle thats plus succinct. Actuellement, j'ai une classe Java avec un tableau statique pour contenir les dernières données x jours, alors que je lis à travers le fichier, je coupe le premier élément et déplacer les autres 6 (pour un total de roulement semaine) en arrière par un. Le traitement de ce tableau statique est fait dans sa propre méthode c'est-à-dire. Ma question: est-ce une approche de conception raisonnable, ou est-il quelque chose d'aveuglante évidente et simple à faire cette tâche Merci les gars a demandé Août 30 11 at 14:33 Merci beaucoup les gars: J'ai reçu le message: utiliser un objet de niveau supérieur et d'exploiter le Les méthodes pertinentes ou un tampon circulaire. De grandes réponses, toutes. Quand vous pensez à cela, vous avez toujours besoin d'accès à l'ensemble du tableau afin que vous puissiez vous débarrasser de cette première entrée - dont je n'étais pas sûr de moi-même. I39m soulagé que je hadn39t raté un liner 1 et a été fondamentalement sur une voie raisonnable, sinon efficace et concis C'est ce que j'aime sur ce site: de haute qualité, des réponses pertinentes de personnes qui connaissent leur sht. Ndash Pete855217 Aug 30 11 at 15:05 Pourquoi initialisez-vous runningTotal to null Quelle est son type Où il est déclaré Il ferait bien si vous mettez des exemples de code qui ressemblent au code Java réel. Je poursuis, ma critique serait la suivante: votre fonction fait trop. Une fonction ou une méthode doit être cohérente. Plus précisément, ils devraient faire une chose et une seule chose. Pire encore, ce qui se passe dans votre boucle for lorsque x 5 Vous copiez runningTotal6 en runningTotal5. Mais alors vous avez deux copies de la même valeur à la position 5 et 6. Dans votre conception, votre movessouffles fonction des éléments de votre tableau calcule le total imprime des choses à l'erreur standard renvoie le total Il fait trop. Ma première suggestion est de ne pas déplacer les choses dans le tableau. Au lieu de cela, implémentez un tampon circulaire et utilisez-le au lieu du tableau. Il simplifiera votre conception. Ma deuxième suggestion est de décomposer les choses en fonctions cohérentes: avoir une structure de données (un buffer circulaire) qui vous permet d'y ajouter (et qui supprime la plus ancienne entrée quand elle atteint sa capacité). Interator ont une fonction qui calcule le total sur l'itérateur (vous ne vous inquiétez pas si vous calculez le total d'un tableau, liste ou bufer circulaire.) Ne l'appelez pas total. Appelez-le somme, qui est ce que vous êtes l'informatique. Thats ce que je fais :) C'est une petite partie de la fonctionnalité de la classe, et il serait excessif d'ajouter trop de code pour le rendre parfait. Vous êtes techniquement correct, et je comprends mon code fait beaucoup39 mais dans le même temps il est parfois préférable d'errer sur le côté de plus petit, code plus clair que d'aller à la perfection. Étant donné mes compétences Java, même faire le pseudocode que vous décrivez compiler aurait me souffler mon budget sur ce (), mais merci pour la description claire. Ndash Pete855217 Aug 31 11 at 2:23 Hmmm, ce n'est pas sur la perfection, mais sur les pratiques industrielles établies que nous connaissons depuis les 3 dernières décennies. Le code propre est toujours celui qui est partitionné. Nous avons des décennies de preuves qui indiquent que c'est la voie à suivre dans le cas général (en termes de rentabilité, de réduction des défauts, de compréhension, etc.). Sauf s'il s'agit d'un code déchiré pour un type unique de chose. Il n'est jamais coûteux de le faire quand on commence une analyse de problème de cette manière. Codage 101, décomposer le problème et le code suit, ni overkill ni difficile) ndash luis. espinal Aug 31 11 at 15:55 Votre tâche est trop simple et l'approche que vous avez adopté est certainement bon pour le travail. Cependant, si vous voulez utiliser une meilleure conception, vous devez vous débarrasser de tout ce mouvement de nombre vous mieux utiliser une file d'attente FIFO et faire bon usage des méthodes push et pop de cette façon le code ne reflètera pas tout mouvement de données, De nouvelles données et de supprimer les données de plus de 7 jours. Répondre Aug 30 11 at 14:49
No comments:
Post a Comment