Pankesh Patel
Pankesh Patel

Reputation: 1302

Calculate average from sources that sends data at different time.

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

Answers (5)

Aaron Digulla
Aaron Digulla

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

ali haider
ali haider

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

Mateusz Kowalczyk
Mateusz Kowalczyk

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

Adam Sznajder
Adam Sznajder

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

epoch
epoch

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

Related Questions