Reputation: 1302
In my current project, I am going to write a function of calculating average Temperature.
A notatable point of this function is that it receives data from many temperature sources at different time. Could you advise me "How can I write a function with such a behavior?"
For instance, following function receives tempSensorData
from many temperature Sensors, which sends temperature data at different time. I need to write a logic of calculating average temperature.
public void calculateRoomAvgTemp(TempStruct tempSensorData) {
// Write logic of calculating Average Temperature.
}
Upvotes: 0
Views: 480
Reputation: 328754
To calculate the average without keeping all historic values in memory (or a database), use a "moving average". This mathematical tool can give you the new average from the last one plus the current value.
Upvotes: 1
Reputation: 20232
one way I could think of - insert values as you receive them into an ArrayList. If you need to calculate the average temperature after each data point that you receive, run through a for loop and average out the data points in the ArrayList to get the required value. One could look into using memoization to avoid running through the loop for all values.
Another option would be to use apache commons math whereby you can use the descriptive statistics option (using a rolling array) to get the mean (average).
I am assuming your code is single threaded. If multithreaded, you could use a thread safe vector (or add locks/synchronization on your own). Hope this helps.
Upvotes: 1
Reputation: 2066
can you store past temperatures in a separate field in the class? I noticed that your method is void, therefore doesn't return anything. I'm going to assume you want to store the average in the separate field. Example:
public class TempCalculator {
private double totalTemp = 0;
private int sensors = 0;
private double averageTemp = 0;
public void calculateRoomAvgTemp(TempStruct tempSensorData) {
totalTemp += tempSensorData.getTemp(); // Assuming getTemp() exists
sensors += 1;
averageTemp = totalTemp / sensors;
}
public double getAvgTemp() {
return averageTemp;
}
}
Of course, this can be done with a list if you want to store temperatures used and shaped to your needs. Hope this helps.
Upvotes: 1
Reputation: 9216
You can create one thread which will calculate the temperature and many which will measure it values from different places. When some measurement is done the thread pushes the result into e.g. LinkedBlockingQueue
. It's important to synchronize this operation because many threads might try to push results at the same time. The thread which calculate average temperature would run in a loop, pop new result from the queue, recalculate the temperature and then once again try to pop another result. As far as the queue will be empty the thread would be blocked on reading from it. In this way you would have an asynchronous communication between threads and the average temperature would be recalculated immediately after the measurements are done.
Upvotes: 0
Reputation: 16615
Why don't you just keep a running average? Assuming that your method gets called each time a temperature reading is taken, you can do the following:
private final List<Double> temps = Collections
.synchronizedList(new ArrayList<Double>());
private double currentAverage = 0d;
public void calculateRoomAvgTemp(TempStruct tempSensorData) {
synchronized (this.temps) {
this.temps.add(tempSensorData.temp);
this.currentAverage = 0d;
for (Double temp : this.temps) {
this.currentAverage += temp;
}
this.currentAverage /= this.temps.size();
}
}
Upvotes: 3