Reputation: 71
My two lists list2
and filetemp
are of the same lengths and contain dates and temperatures. A few of the elements in the lists are shown below:
[1946-01-12, 1946-01-12, 1946-01-12, 1946-01-13, 1946-01-13, 1946-01-13, 1946-01-14, 1946-01-14, 1946-01-14]
[-1.3, 0.3, -2.8, -6.2, -4.7, -4.3, -1.5, -0.2, -0.4]
I want to put them in a hashmap with dates as key and temperature as value. Since I have several temperature values corresponding to each date, I want to sum the temperature values for each day (or if possible calculate average temperature for each day) so that each date in the map corresponds to the average temperature of that date. My problem now is that my map looks like:
1946-01-12: -2.8
1946-01-13: -4.3
1946-01-14: -0.4
so instead of summing for example -1.5+(-0.2)+(-0.4) for date 1946-01-14 it just returns the last temperature of that date. Does anyone know how to fix it?
public Map<LocalDate, Double> avarageTemperatures(LocalDate dateFrom, LocalDate dateTo) {
List<LocalDate> list2 = new ArrayList<>();
for (Weather weather : weatherData) {
list2.add(weather.getDateTime());
}
Map<LocalDate, Double> map = new HashMap<>();
List<Double> filetemp = new ArrayList<>();
for (Weather weather : weatherData) {
filetemp.add(weather.getTemperature());
}
Double val= 0.0;
for (int i=1; i<list2.size(); i++) {
if(list2.get(i)==list2.get(i-1)) {
val+= filetemp.get(i);
map.put(list2.get(i), val);
} else {
val=filetemp.get(i);
map.put(list2.get(i), val);
}
}
Set<Map.Entry<LocalDate, Double>> entrySet = map.entrySet();
for(Map.Entry<LocalDate,Double> entry : entrySet) {
if(!entry.getKey().isAfter(dateTo) && !entry.getKey().isBefore(dateFrom)) {
System.out.println(entry.getKey()+": "+(entry.getValue()));
}
}
return map;
}
Upvotes: 1
Views: 172
Reputation: 40034
Well, here is one way using streams
and creating a map of maps. The inner map simply holds the sum
and average
temperatures. A List
could also have been used but the map allows symbolic indexing to help keep things straight.
It works as follows:
Collectors.teeing
method to create two streams. The first does a frequency count of dates. The second, adds the temps. Both end up in maps with the dates as keys.TreeMap
is used for the outer map to sort the keys in their natural order.
List<String> dates =
List.of("1946-01-12", "1946-01-12", "1946-01-12",
"1946-01-13", "1946-01-13", "1946-01-13",
"1946-01-14", "1946-01-14", "1946-01-14");
List<Double> temps = List.of(-1.3, 0.3, -2.8, -6.2, -4.7,
-4.3, -1.5, -0.2, -0.4);
Map<String,Map<String, Double>> data = IntStream
.range(0,
dates.size())
.boxed()
.collect(Collectors.teeing(
Collectors.groupingBy(i -> dates.get(i),
Collectors.counting()),
Collectors.groupingBy(i -> dates.get(i),
Collectors.summingDouble(
i -> temps.get(i))),
(counts, temp) -> temp.keySet().stream()
.collect(Collectors.toMap(k->k,
k->Map.of("SUM", temp.get(k), "AVG",temp.get(k)
/ counts.get(k)), (m,n)->n, TreeMap::new))));
for (String k : data.keySet()) {
System.out.printf("For %s - sum of temperatures was %6.3f%n",k,data.get(k).get("SUM"));
System.out.printf("For %s - average temp was %6.3f%n",k,data.get(k).get("AVG"));
System.out.println();
}
It prints the following:
For 1946-01-12 - sum of temperatures was -3.800
For 1946-01-12 - average temp was -1.267
For 1946-01-13 - sum of temperatures was -15.200
For 1946-01-13 - average temp was -5.067
For 1946-01-14 - sum of temperatures was -2.100
For 1946-01-14 - average temp was -0.700
Upvotes: 2
Reputation: 2560
Hope this helps:
List<String> dates = Arrays.asList("1946-01-12", "1946-01-12", "1946-01-12", "1946-01-13", "1946-01-13", "1946-01-13", "1946-01-14", "1946-01-14", "1946-01-14");
List<Double> values = Arrays.asList(-1.3, 0.3, -2.8, -6.2, -4.7, -4.3, -1.5, -0.2, -0.4);
Map<String, DoubleSummaryStatistics> res = IntStream
.range(0, dates.size())
.boxed()
.map(index -> new Pair<>(dates.get(index), values.get(index)))
.collect(groupingBy(Pair::getKey,
summarizingDouble(Pair::getValue)));
System.out.println(res);
and the result:
{1946-01-14=DoubleSummaryStatistics{count=3, sum=-2.100000, min=-1.500000, average=-0.700000, max=-0.200000},
1946-01-12=DoubleSummaryStatistics{count=3, sum=-3.800000, min=-2.800000, average=-1.266667, max=0.300000},
1946-01-13=DoubleSummaryStatistics{count=3, sum=-15.200000, min=-6.200000, average=-5.066667, max=-4.300000}}
Upvotes: 0
Reputation: 5246
This is one way you can do it. To get a List of Weather objects like you have we create a List of Weather objects using the array of String and array of Double values. From that List we simply collect using Collectors#groupingBy which allows us to determine the key we want to group by, which in this case is LocalDate, and the Collector used to group all the relevant key values together, which in this case is Collectors#summingDouble since we want to sum all double values.
String[] dates = {
"1946-01-12", "1946-01-12", "1946-01-12", "1946-01-13", "1946-01-13", "1946-01-13",
"1946-01-14", "1946-01-14", "1946-01-14"
};
double[] temperatures = {-1.3, 0.3, -2.8, -6.2, -4.7, -4.3, -1.5, -0.2, -0.4};
class Weather {
private final LocalDate date;
private final double temperature;
Weather(LocalDate date, double temperature) {
this.date = date;
this.temperature = temperature;
}
public LocalDate getDate() {
return date;
}
public double getTemperature() {
return temperature;
}
}
List<Weather> weather = IntStream.range(0, dates.length)
.mapToObj(index -> new Weather(LocalDate.parse(dates[index]), temperatures[index]))
.collect(Collectors.toList());
Map<LocalDate, Double> temperaturesSum = weather.stream()
.collect(Collectors.groupingBy(Weather::getDate,
Collectors.summingDouble(Weather::getTemperature)));
Map<LocalDate, Double> temperaturesAverage = weather.stream()
.collect(Collectors.groupingBy(Weather::getDate,
Collectors.averagingDouble(Weather::getTemperature)));
System.out.println("sum: " + temperaturesSum);
System.out.println("average: " + temperaturesAverage);
sum: {1946-01-12=-3.8, 1946-01-13=-15.2, 1946-01-14=-2.1}
average: {1946-01-12=-1.2666666666666666, 1946-01-13=-5.066666666666666, 1946-01-14=-0.7000000000000001}
Upvotes: 1