J'ai un projet qui utilise une ArrayList pour stocker les horodatages. Avec cette ArrayList, je calcule le temps de stationnement moyen pour chaque voiture dans un garage. Si je lance mon projet pendant 5 minutes, disons, cette ArrayList spécifique a déjà été chargée avec environ 10 000 horodatages différents. Par conséquent, je veux limiter l'ensemble de ArrayList à seulement 250 pour l'empêcher de surcharger. Si la ArrayList a une certaine taille, il faut une éternité pour la parcourir. Il doit pousser les nouvelles heures dans ArrayList mais supprimer les plus anciennes pour pouvoir toujours calculer la durée moyenne. Comment puis-je y parvenir?
La ArrayList
public BigDecimal getAverageTime() { float totalTime = 0.0f; for(Float time : times) { totalTime += time; } float average = totalTime / times.size(); average = average / 60; int hour = (int) average; int minuut = (int) (60 * (average - hour)); float temp1 = (float) minuut / 100; float temp2 = hour + temp1; return round(temp2, 2); }
Ajout des heures à la ArrayList
private void carsPaying() { // Let cars pay. float total = 0.0f; int i = 0; while (paymentCarQueue.carsInQueue()>0 && i < Car.getPaymentSpeed()){ Car car = paymentCarQueue.removeCar(); if(currentDay != Time.getDay()) { weeklyRevenue[Time.getDay()] = 0; currentDay = Time.getDay(); } // TODO Handle payment. float payment = car.getTotalMinutes() * 0.042f; weeklyRevenue[Time.getDay()] += payment; revenue += payment; carLeavesSpot(car); numberOfParkedCars--; numberOfCarsLeft++; float timeInFloat = car.getTotalMinutes(); times.add(timeInFloat); i++; } System.out.println(total); }
Calculer le temps moyen
private ArrayList<Float> times = new ArrayList<Float>();
Merci d'avance
4 Réponses :
Je suggérerais une stratégie comme celle-ci
Queue<Float> times = new ArrayDeque<>(); final static int MAX_SIZE = 250; public void addTime(float time) { if(times.size() == MAX_SIZE) times.poll(); times.add(time); } // continue your average calculation the maximum size the times queue will ever // get is 250
Cela laissera-t-il encore des temps plus récents dans la file d'attente? Donc, si la file d'attente est pleine et que je pousse une nouvelle heure dans la file d'attente, celle-ci sera ignorée? ou également poussé dans la file d'attente et un autre sera supprimé?
il supprimera la première heure insérée, c'est-à-dire la plus ancienne, et insérera votre nouvelle heure à la fin de la file d'attente
Si vous souhaitez utiliser Guava, vous pouvez utiliser une classe appelée EvictingQueue voir https://google.github.io/guava/releases/22.0/api/docs/index.html?com/google/common/collect/EvictingQueue. html . Ce n'est pas une liste mais elle implémente des itérations, ce qui signifie que vous pouvez facilement la rechercher.
est-ce vraiment une bonne idée de retirer toute la goyave juste pour une fonctionnalité simple qui pourrait facilement être obtenue par une file d'attente
normale et un peu de logique.
Je préfère ne pas écrire de code que quelqu'un d'autre a probablement mieux écrit; J'utilise apache commons pour la manipulation de chaînes et apache IO pour les E / S courantes. Vous pouvez supprimer le code non utilisé si vous le souhaitez lorsque vous effectuez votre génération avec plusieurs outils. Cela dépend si vous pensez que vous êtes meilleur que les autres que je pense; moi je suis une personne imparfaite :)
je ne dis pas que je peux écrire un meilleur code que ce que les bibliothèques offrent déjà, le code déjà existant a été testé et utilisé par des milliers de développeurs donc pas de questions là-bas, je mentionnais seulement le fait qu'il est peut-être exagéré de tirer une bibliothèque entière ( goyave
dans ce cas) pour quelque chose que vous pouvez réaliser en utilisant simplement ce qui est déjà offert par le jdk :)
Si le nombre d'éléments est fixe, vous devez utiliser un tableau à la place. Il est facile d'écraser les éléments les plus anciens en utilisant l'opérateur modulo, comme ceci:
private static final int MAX_SIZE = 250; private float[] times = new float[MAX_SIZE]; private void carsPaying() { // ... while (paymentCarQueue.carsInQueue() > 0 && i < Car.getPaymentSpeed()) { // ... times[i % MAX_SIZE] = timeInFloat; i++; } }
Vous pouvez utiliser add (index int, élément E)
au lieu de add (élément E)
et réinitialiser le compteur à 0
pour conserver éléments plus récents:
LinkedList<Float> times = new LinkedList<>(); //... while (paymentCarQueue.carsInQueue()>0 && i < Car.getPaymentSpeed()){ // ... float timeInFloat = car.getTotalMinutes(); if (times.size() == MAX_TIMES-1) { times.removeFirst()}; times.addLast(timeInFloat); }
Notez qu'il ne maintiendra pas l'ordre des éléments en fonction de leur récente.
Pour le maintenir, utiliser une Queue
comme LinkedList
est une bonne possibilité car l'ajout ou la suppression au début ou à la fin de celle-ci est assez bon marché.
Par exemple pour maintenir des éléments par temps croissant:
int i = 0; while (paymentCarQueue.carsInQueue()>0 && i < Car.getPaymentSpeed()){ // ... float timeInFloat = car.getTotalMinutes(); times.add(i, timeInFloat); i++; if (i == MAX_TIMES-1) { i = 0 }; }
Voulez-vous supprimer les anciennes données de
ArrayList
après avoir atteint 250?Ouais si c'est possible? Ne laisser entrer que les plus récents pour qu'il soit toujours mis à jour si cela a du sens?
Vous utilisez
float
pour les valeurs monétaires. Ne fais pas ça.