Home > database >  Get min/max values from fields in array
Get min/max values from fields in array

Time:05-11

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 OptionalDoubles, 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

  •  Tags:  
  • java
  • Related