So I have a class called station and it holds a list of readings that holds temperature, windSpeed and pressure.
What would be the nicest way of getting min/max values of temperature, windSpeed and pressure?
This is how I have done it. But I don't know it feels wrong.
public static void setMinMaxValues(Station station) {
station.temperatureMin = station.windSpeedMin = station.pressureMin = Float.MAX_VALUE;
for (Reading reading : station.readings) {
if (station.temperatureMin > reading.temperature) station.temperatureMin = reading.temperature;
if (station.temperatureMax < reading.temperature) station.temperatureMax = reading.temperature;
if (station.windSpeedMin > reading.windSpeed) station.windSpeedMin = reading.windSpeed;
if (station.windSpeedMax < reading.windSpeed) station.windSpeedMax = reading.windSpeed;
if (station.pressureMin > reading.pressure) station.pressureMin = reading.pressure;
if (station.pressureMax < reading.pressure) station.pressureMax = reading.pressure;
}
}
I would appreciate any suggestions of how to improve it, or what could I look into to make it better.
CodePudding user response:
You could use streaming to compute the them without an explicit loop.
public static void setMinMaxValues(Station station) {
station.temperatureMin = station.readings.stream().mapToDouble(s -> s.temperature).min().orElse(Double.NaN);
station.temperatureMax = station.readings.stream().mapToDouble(s -> s.temperature).max().orElse(Double.NaN);
station.windSpeedMin = station.readings.stream().mapToDouble(s -> s.windSpeed).min().orElse(Double.NaN);
station.windSpeedMax = station.readings.stream().mapToDouble(s -> s.windSpeed).max().orElse(Double.NaN);
station.pressureMin = station.readings.stream().mapToDouble(s -> s.pressure).min().orElse(Double.NaN);
station.pressureMax = station.readings.stream().mapToDouble(s -> s.pressure).max().orElse(Double.NaN);
}
Computing the values in one shot more clearly expresses intention, IMO. It also gives you better
control over how to handle a lack of readings: you could use NaN
as shown above, or you could
leave them as OptionalDouble
s, or you could decline to update the old values.
It does, however, require six passes over the readings, which is a bummer. You could reduce it to three by using summarizingDouble
to compute the min and maxes of each value simultaneously.
public static void setMinMaxValues(Station station) {
DoubleSummaryStatistics temperatureStats = station.readings.stream().collect(s -> s.temperature);
DoubleSummaryStatistics windSpeedStats = station.readings.stream().collect(s -> s.windSpeed);
DoubleSummaryStatistics pressureStats = station.readings.stream().collect(s -> s.pressure);
station.temperatureMin = temperatureStats.getMin();
station.temperatureMax = temperatureStats.getMax();
station.windSpeedMin = windSpeedStats.getMin();
station.windSpeedMax = windSpeedStats.getMax();
station.pressureMin = pressureStats.getMin();
station.pressureMax = pressureStats.getMax();
}
If there are no readings this will assign ∞ to the mins and -∞ to the maxes.
CodePudding user response:
Check out the Math Class. You can e. g. replace
if (station.temperatureMin > reading.temperature) station.temperatureMin = reading.temperature;
with
station.temperatureMin = Math.min(station.temperatureMin, reading.temperature);
There of course is a Math.max()
as well