Максимальное значение потока Java от среднего

Мне нужно получить название страны максимальной средней температуры.

Я использовал следующее, чтобы получить средние температуры

 this.getTemperatures()
                .stream()
                .collect(Collectors.groupingBy(Temperature::getCountry,
                        Collectors.averagingDouble(Temperature::getAverageTemperature)))

Как я могу получить максимальное или минимальное среднее название страны из этого списка средних температур?


person Community    schedule 10.01.2019    source источник
comment
что вы подразумеваете под максимальным средним? пример ?   -  person Schidu Luca    schedule 10.01.2019
comment
Есть имя класса IntSummaryStatistics , вы пробовали?   -  person Vishwa Ratna    schedule 10.01.2019
comment
@SchiduLuca У меня есть список средних температур, сгруппированных по странам. Теперь я хочу получить страну с максимальным значением из этого списка, используя потоки.   -  person    schedule 10.01.2019


Ответы (4)


Мне это не очень нравится, потому что много кода повторяется, но это сработает. Я не могу придумать способ избежать повторения, не ухудшив код.

Это также повторяет все записи карты дважды, но, учитывая, что стран всего 195, мы говорим о максимум 195 дополнительных итерациях (если у вас есть измерения для каждой), и это совершенно ничтожно мало для ЦП.

String max = countryToAvgTemp.entrySet().stream()      //stream all entries
    .max(Map.Entry.comparingByValue())                 //get the max by comparing entry value
    .map(Map.Entry::getKey)                            //grab the key   
    .orElseThrow(() -> new RuntimeException("No max")); //e.g. if the list is empty

String min = countryToAvgTemp.entrySet().stream()
    .min(Map.Entry.comparingByValue())
    .map(Map.Entry::getKey)
    .orElseThrow(() -> new RuntimeException("No min"));

Если вы хотите выполнить итерацию только один раз, вы можете написать свой собственный сборщик, который возвращает что-то вроде MinMax<String>. Я написал один, но код не был отличным. Лучше держать его простым.

person Michael    schedule 10.01.2019
comment
@Аомине Спасибо. Я удивлен, что IntelliJ не предупредил меня об этом. Обычно для таких вещей вполне подходит. - person Michael; 10.01.2019
comment
Или за один проход, используя SummaryStatistics из этого ответа: SummaryStatistics<Map.Entry<String,Double>> s = countryToAvgTemp.entrySet().stream() .collect(SummaryStatistics.statistics(Map.Entry.comparingByValue())); String min = s.getMin().getKey(), max = s.getMax().getKey(); - person Holger; 10.01.2019
comment
@Holger Конечно, но я бы не рекомендовал брать весь класс из Stack Overflow без каких-либо тестов или чего-то еще. - person Michael; 10.01.2019
comment
Ну, многие люди используют целые библиотеки классов без каких-либо тестов, просто потому, что это библиотека с именем. Я могу вам сказать, что у меня есть тесты для этого класса в моей кодовой базе, и любому разработчику не составит труда написать для него тесты. В итоге при реализации своими силами вместо того, чтобы брать из Stackoverflow, им пришлось писать такие же тесты. - person Holger; 10.01.2019

Использовать

Collections.min(temperatureMap.entrySet(), Comparator.comparingInt(Map.Entry::getValue)).getValue()

а также

Collections.max(temperatureMap.entrySet(),  Comparator.comparingInt(Map.Entry::getValue)).getValue()
person Leonardo    schedule 10.01.2019
comment
Это Map.Entry, которые не сопоставимы. - person Michael; 10.01.2019

Если вы хотите получить максимальное или минимальное среднее название страны, вы можете отсортировать список температур, а затем получить первый и последний элементы. Но для вашей работы не нужен отсортированный список, это не очень хороший метод, метод @Michael очень хорош для ты.

       List<Temperature> temperatures = Arrays.asList(
                new Temperature("a",10),
                new Temperature("b",11),
                new Temperature("c",12),
                new Temperature("d",13),
                new Temperature("e",14),
                new Temperature("f",15),
                new Temperature("g",16),
                new Temperature("h",17));

        temperatures = temperatures.stream().sorted(new Comparator<Temperature>() {
            @Override
            public int compare(Temperature o1, Temperature o2) {
                return (int) (o1.getAverageTemperature() - o2.getAverageTemperature());
            }
        }).collect(Collectors.toList());

        String min = temperatures.get(0).getCountry();
        String max = temperatures.get(temperatures.size()-1).getCountry();
person TongChen    schedule 10.01.2019

Вы можете попробовать DoubleSummaryStatistics:

this.getTemperatures()
            .stream()
            .collect(Collectors.groupingBy(Temperature::getCountry,
                    Collectors.summarizingDouble(Temperature::getAverageTemperature)));

это вернет карту:

Map<Country, DoubleSummaryStatistics>

Таким образом, с помощью DoubleSummaryStatistics вы можете получить количество, сумму, минимум, максимум, среднее значение для каждой страны.

person Twister    schedule 11.01.2019