Saturday, August 6, 2016

Stream API ile İstatistik Hesaplamak


Java'da veriler üzerinde hesaplama yapmak için Collection API içinde yer alan torbaları kullanarak onları bellekte organize ederiz. Organize ettiğimiz bu veriler üzerinde minimum, maksimum, ortalama değer gibi istatistiksel hesaplamalar yapmak için ise JavaSE  8 ile birlikte gelen Stream API'nin yeteneklerini kullanmamız gerekir. Stream API'nin bu türden yeteneklerini örnek problemler çözerek çalışalım:

1. Her bir kıtada kaç ülke olduğunu bulalım. Önce ülkeleri kıtalara göre kümelememiz ve her bir kümede kaç ülke olduğunu saymamız gerekir:
package com.example.exercises;

import com.example.dao.InMemoryWorldDao;
import com.example.dao.WorldDao;
import com.example.domain.Country;

import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class Exercise1 {

    public static void main(String[] args) {
        WorldDao worldDao = InMemoryWorldDao.getInstance();
        Map<String, Long> numOfCountriesByContinent =
          worldDao.findAllCountries()
                .stream()
                .collect(Collectors.groupingBy(Country::getContinent,Collectors.counting()));
        Consumer<Map.Entry> printEntry =
                entry -> System.out.println(String.format("%s: %s",entry.getKey(),entry.getValue()));
        numOfCountriesByContinent.entrySet().forEach(printEntry);
    }
}
İşte kıta ülkelerinin sayıları:
South America: 14
Asia: 51
Europe: 46
Africa: 58
Antarctica: 5
North America: 37
Oceania: 28

2. Şimdi her kıtanın GNP (Gross National Product)(=Gayri Safi Milli Hasıla) değerine göre en zengin ülkesini bulalım:
package com.example.exercises;

import com.example.dao.InMemoryWorldDao;
import com.example.dao.WorldDao;
import com.example.domain.Country;

import java.util.Comparator;
import java.util.Map;
import java.util.Optional;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class Exercise2 {

    public static void main(String[] args) {
        WorldDao worldDao = InMemoryWorldDao.getInstance();
        Map<String, Optional<Country>> richestCountryByContinent =
          worldDao.findAllCountries()
                .stream()
                .collect(
                    Collectors.groupingBy(Country::getContinent,
                    Collectors.reducing(BinaryOperator.maxBy(Comparator.comparing(Country::getGnp))))
                );
        Consumer<Map.Entry<String,Optional<Country>>> printEntry =
                entry -> System.out.println(String.format("%s: %s",entry.getKey(),entry.getValue().get()));
        richestCountryByContinent.entrySet().forEach(printEntry);
    }
}
İşte kıtaların en zengin ülkeleri:
South America: Country{gnp=776739.0, code='BRA', name='Brazil', continent='South America', surfaceArea=8547403.0, population=170115000}
Asia: Country{gnp=3787042.0, code='JPN', name='Japan', continent='Asia', surfaceArea=377829.0, population=126714000}
Europe: Country{gnp=2133367.0, code='DEU', name='Germany', continent='Europe', surfaceArea=357022.0, population=82164700}
Africa: Country{gnp=116729.0, code='ZAF', name='South Africa', continent='Africa', surfaceArea=1221037.0, population=40377000}
Antarctica: Country{gnp=0.0, code='ATA', name='Antarctica', continent='Antarctica', surfaceArea=1.312E7, population=0}
North America: Country{gnp=8510700.0, code='USA', name='United States', continent='North America', surfaceArea=9363520.0, population=278357000}
Oceania: Country{gnp=351182.0, code='AUS', name='Australia', continent='Oceania', surfaceArea=7741220.0, population=18886000}

3. Dünya ülkelerinin minimum, maksimum ve ortalama nüfus sayılarını hesaplayalım:
package com.example.exercises;

import com.example.dao.InMemoryWorldDao;
import com.example.dao.WorldDao;
import com.example.domain.Country;

import java.util.LongSummaryStatistics;
import java.util.stream.Collectors;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class Exercise3 {

    public static void main(String[] args) {
        WorldDao worldDao = InMemoryWorldDao.getInstance();
        LongSummaryStatistics populationSummary =
          worldDao.findAllCountries()
                .stream()
                .collect(Collectors.summarizingLong(Country::getPopulation));
        System.out.println(populationSummary);
    }
}
İşte dünya nüfusu ile ilgili istatistikler:
LongSummaryStatistics{count=239, sum=6078749450, min=0, average=25434098.117155, max=1277558000}

4. Bir önceki hesaplamayı bu sefer kıta özelinde yapalım ve her bir kıta için kıta ülkelerinin minimum, maksimum ve ortalama nüfus sayılarını hesaplayalım:
package com.example.exercises;

import com.example.dao.InMemoryWorldDao;
import com.example.dao.WorldDao;
import com.example.domain.Country;

import java.util.LongSummaryStatistics;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class Exercise4 {

    public static void main(String[] args) {
        WorldDao worldDao = InMemoryWorldDao.getInstance();
        Map<String,LongSummaryStatistics> populationSummaryByContinent =
          worldDao.findAllCountries()
                .stream()
                .collect(Collectors.groupingBy(Country::getContinent,Collectors.summarizingLong(Country::getPopulation)));
        Consumer<Map.Entry> printEntry =
                entry -> System.out.println(String.format("%s: %s",entry.getKey(),entry.getValue()));
        populationSummaryByContinent.entrySet().forEach(printEntry);

    }
}
İşte sonuçlar:
South America: LongSummaryStatistics{count=14, sum=345780000, min=2000, average=24698571.428571, max=170115000}
Asia: LongSummaryStatistics{count=51, sum=3705025700, min=286000, average=72647562.745098, max=1277558000}
Europe: LongSummaryStatistics{count=46, sum=730074600, min=1000, average=15871186.956522, max=146934000}
Africa: LongSummaryStatistics{count=58, sum=784475000, min=0, average=13525431.034483, max=111506000}
Antarctica: LongSummaryStatistics{count=5, sum=0, min=0, average=0.000000, max=0}
North America: LongSummaryStatistics{count=37, sum=482993000, min=7000, average=13053864.864865, max=278357000}
Oceania: LongSummaryStatistics{count=28, sum=30401150, min=0, average=1085755.357143, max=18886000}

5. Şimdi 3 ve 4'de yaptığımız analizi biraz değiştireceğiz. Minimum, maksimum ve ortalama nüfusu hesaplamıştık. Şimdi ise minimum ve maksimum nüfusa sahip ülkeleri bulalım:
package com.example.stream;

import com.example.domain.Country;

import java.util.Comparator;
import java.util.function.Consumer;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class CountrySummaryStatistics implements Consumer<Country> {
    private Comparator<Country> comparator;
    private Country min;
    private Country max;
    private long count;

    public CountrySummaryStatistics() {
    }

    public CountrySummaryStatistics(Comparator<Country> comparator) {
        this.comparator = comparator;
    }

    @Override
    public void accept(Country value) {
        count++;
        min = min!=null && comparator.compare(min,value)<=0 ? min : value;
        max = max!=null && comparator.compare(max,value)>=0 ? max : value;
    }

    public void combine(CountrySummaryStatistics other) {
        this.min= comparator.compare(this.min,other.min)<=0 ? this.min : other.min;
        this.max= comparator.compare(this.max,other.max)>=0 ? this.max : other.max;
    }

    public Country getMin() {
        return min;
    }

    public void setMin(Country min) {
        this.min = min;
    }

    public Country getMax() {
        return max;
    }

    public void setMax(Country max) {
        this.max = max;
    }

    public long getCount() {
        return count;
    }

    public void setCount(long count) {
        this.count = count;
    }

    @Override
    public String toString() {
        return "CountrySummaryStatistics{" +
                "min=" + getMin() +
                ", max=" + getMax() +
                ", count=" + getCount() +
                '}';
    }

}

package com.example.exercises;

import com.example.dao.InMemoryWorldDao;
import com.example.dao.WorldDao;
import com.example.stream.CountrySummaryStatistics;

import java.util.function.Supplier;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class Exercise5 {

    public static void main(String[] args) {
        WorldDao worldDao = InMemoryWorldDao.getInstance();
        Supplier<CountrySummaryStatistics> countrySummaryStatisticsSupplier=
                () -> new CountrySummaryStatistics((l,r)-> Long.compare(l.getPopulation(),r.getPopulation()));
        CountrySummaryStatistics countrySummaryStatistics =
          worldDao.findAllCountries()
                .stream()
                .collect(countrySummaryStatisticsSupplier,CountrySummaryStatistics::accept,CountrySummaryStatistics::combine);
        System.out.println(countrySummaryStatistics);
    }
}
İşte en az ve en çok kalabalık ülkeler:
CountrySummaryStatistics{
    min=Country{gnp=0.0, code='ATA', name='Antarctica', continent='Antarctica', surfaceArea=1.312E7, population=0}, 
    max=Country{gnp=982268.0, code='CHN', name='China', continent='Asia', surfaceArea=9572900.0, population=1277558000}, 
    count=239
}
Sonuçlar şaşırtıcı olmadı ve en kalabalık ülke olarak Çin'i bulduk.

6. Bir önceki incelemeyi bu kez kıta özelinde yapalım ve kıtalardaki en az ve en fazla nüfusa sahip ülkeleri bulalım:

package com.example.exercises;

import com.example.dao.InMemoryWorldDao;
import com.example.dao.WorldDao;
import com.example.domain.Country;
import com.example.stream.CountrySummaryStatistics;

import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class Exercise6 {

    public static void main(String[] args) {
        WorldDao worldDao = InMemoryWorldDao.getInstance();
        Supplier<CountrySummaryStatistics> countrySummaryStatisticsSupplier=
                () -> new CountrySummaryStatistics((l,r)-> Long.compare(l.getPopulation(),r.getPopulation()));
        BiConsumer<CountrySummaryStatistics, Country> accumulator =
                (a,c) -> a.accept(c);
        BinaryOperator<CountrySummaryStatistics> combiner= (l,r) -> { l.combine(r); return l;};
        Map<String,CountrySummaryStatistics> continentStatistics =
          worldDao.findAllCountries()
                .stream()
                .collect(Collectors.groupingBy(Country::getContinent,Collector.of(countrySummaryStatisticsSupplier,accumulator,combiner)));
        Consumer<Map.Entry> printEntry =
                entry -> System.out.println(String.format("%s: %s",entry.getKey(),entry.getValue()));
        continentStatistics.entrySet().forEach(printEntry);

    }
}
İşte kıtalardaki en az ve en çok kalabalık ülkelerin listesi:
South America: CountrySummaryStatistics{
   min=Country{gnp=0.0, code='FLK', name='Falkland Islands', continent='South America', surfaceArea=12173.0, population=2000}, 
   max=Country{gnp=776739.0, code='BRA', name='Brazil', continent='South America', surfaceArea=8547403.0, population=170115000}, 
   count=14
}
Asia: CountrySummaryStatistics{
   min=Country{gnp=199.0, code='MDV', name='Maldives', continent='Asia', surfaceArea=298.0, population=286000}, 
   max=Country{gnp=982268.0, code='CHN', name='China', continent='Asia', surfaceArea=9572900.0, population=1277558000}, 
   count=51
}
Europe: CountrySummaryStatistics{
   min=Country{gnp=9.0, code='VAT', name='Holy See (Vatican City State)', continent='Europe', surfaceArea=0.4, population=1000}, 
   max=Country{gnp=276608.0, code='RUS', name='Russian Federation', continent='Europe', surfaceArea=1.70754E7, population=146934000}, 
   count=46
}
Africa: CountrySummaryStatistics{
   min=Country{gnp=0.0, code='IOT', name='British Indian Ocean Territory', continent='Africa', surfaceArea=78.0, population=0},    
   max=Country{gnp=65707.0, code='NGA', name='Nigeria', continent='Africa', surfaceArea=923768.0, population=111506000}, 
   count=58
}
Antarctica: CountrySummaryStatistics{
   min=Country{gnp=0.0, code='ATA', name='Antarctica', continent='Antarctica', surfaceArea=1.312E7, population=0}, 
   max=Country{gnp=0.0, code='ATA', name='Antarctica', continent='Antarctica', surfaceArea=1.312E7, population=0}, 
   count=5
}
North America: CountrySummaryStatistics{
   min=Country{gnp=0.0, code='SPM', name='Saint Pierre and Miquelon', continent='North America', surfaceArea=242.0, population=7000}, 
   max=Country{gnp=8510700.0, code='USA', name='United States', continent='North America', surfaceArea=9363520.0, population=278357000}, 
   count=37
}
Oceania: CountrySummaryStatistics{
   min=Country{gnp=0.0, code='UMI', name='United States Minor Outlying Islands', continent='Oceania', surfaceArea=16.0, population=0}, 
   max=Country{gnp=351182.0, code='AUS', name='Australia', continent='Oceania', surfaceArea=7741220.0, population=18886000}, 
   count=28
}

7. Şimdi ülkeleri kıtalara bölelim ve kıtalardaki ülkelerin listesini alalım:
package com.example.exercises;

import com.example.dao.InMemoryWorldDao;
import com.example.dao.WorldDao;
import com.example.domain.Country;

import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class Exercise7 {

    public static void main(String[] args) {
        WorldDao worldDao = InMemoryWorldDao.getInstance();
        Map<String,List<String>> countryNamesByContinent =
          worldDao.findAllCountries()
                .stream()
                .collect(Collectors.groupingBy(Country::getContinent,Collectors.mapping(Country::getName,Collectors.toList())));
        Consumer<Map.Entry> printEntry =
                entry -> System.out.println(String.format("%s: %s",entry.getKey(),entry.getValue()));
        countryNamesByContinent.entrySet().forEach(printEntry);

    }
}
İşte kıtalardaki ülkelerin, sadece adlarından oluşan listesi:
South America: [Suriname, Argentina, Falkland Islands, Chile, Paraguay, Peru, French Guiana, Guyana, Uruguay, Colombia, Ecuador, Venezuela, Bolivia, Brazil]
Asia: [Malaysia, Taiwan, Oman, United Arab Emirates, Armenia, Uzbekistan, Bhutan, Iran, Qatar, Iraq, Thailand, Israel, Kuwait, Pakistan, Singapore, Kyrgyzstan, China, North Korea, Cambodia, Indonesia, Tajikistan, Vietnam, Cyprus, Bangladesh, Sri Lanka, Palestine, Syria, Myanmar, Turkmenistan, Yemen, Afghanistan, Mongolia, Nepal, Bahrain, East Timor, Azerbaijan, Macao, Georgia, Philippines, South Korea, Laos, Lebanon, Maldives, Hong Kong, Jordan, India, Kazakstan, Saudi Arabia, Japan, Turkey, Brunei]
Europe: [Poland, Ireland, Netherlands, Slovakia, Slovenia, Sweden, Iceland, Macedonia, Belgium, Liechtenstein, Russian Federation, Italy, Ukraine, Switzerland, Croatia, Portugal, Malta, Austria, Yugoslavia, Bulgaria, Czech Republic, Norway, Greece, United Kingdom, Svalbard and Jan Mayen, Bosnia and Herzegovina, Hungary, France, Denmark, Faroe Islands, Holy See (Vatican City State), San Marino, Belarus, Spain, Estonia, Albania, Monaco, Moldova, Gibraltar, Romania, Andorra, Lithuania, Finland, Luxembourg, Germany, Latvia]
Africa: [Sao Tome and Principe, Sudan, Gambia, Mayotte, Kenya, Guinea-Bissau, Senegal, Togo, Burundi, Equatorial Guinea, Algeria, Benin, Swaziland, Tanzania, Burkina Faso, Djibouti, R‚union, Mali, Botswana, Saint Helena, Seychelles, Rwanda, Gabon, Zimbabwe, C“te d?Ivoire, Angola, Mozambique, Namibia, Sierra Leone, Cameroon, Eritrea, Morocco, Mauritania, Congo, The Democratic Republic of the, Congo, Western Sahara, Comoros, Zambia, Somalia, Ethiopia, Niger, Ghana, Cape Verde, Madagascar, Liberia, Libyan Arab Jamahiriya, Central African Republic, Lesotho, Nigeria, Mauritius, Guinea, Chad, Malawi, Tunisia, Uganda, British Indian Ocean Territory, Egypt, South Africa]
Antarctica: [Antarctica, French Southern territories, South Georgia and the South Sandwich Islands, Bouvet Island, Heard Island and McDonald Islands]
North America: [Guadeloupe, Cuba, Aruba, Antigua and Barbuda, Panama, Puerto Rico, Cayman Islands, Grenada, Haiti, Greenland, Bahamas, Dominica, Guatemala, Anguilla, El Salvador, Dominican Republic, Saint Kitts and Nevis, Saint Vincent and the Grenadines, Belize, United States, Bermuda, Montserrat, Martinique, Saint Pierre and Miquelon, Saint Lucia, Virgin Islands, British, Canada, Turks and Caicos Islands, Costa Rica, Mexico, Netherlands Antilles, Trinidad and Tobago, Nicaragua, Barbados, Jamaica, Virgin Islands, U.S., Honduras]
Oceania: [New Zealand, Fiji Islands, Papua New Guinea, Marshall Islands, Wallis and Futuna, American Samoa, Christmas Island, Australia, United States Minor Outlying Islands, Tokelau, Kiribati, Pitcairn, Northern Mariana Islands, Samoa, Solomon Islands, Nauru, Guam, Micronesia, Federated States of, Tonga, New Caledonia, French Polynesia, Cook Islands, Vanuatu, Norfolk Island, Palau, Cocos (Keeling) Islands, Tuvalu, Niue]

8. Bir önceki çalışmada elde edilen şehir adlarından oluşan listenin sıralı olmasını istiyoruz:
package com.example.exercises;

import com.example.dao.InMemoryWorldDao;
import com.example.dao.WorldDao;
import com.example.domain.Country;

import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class Exercise8 {

    public static void main(String[] args) {
        WorldDao worldDao = InMemoryWorldDao.getInstance();
        Supplier<Set<String>> defaultConstructorOfTreeSet= TreeSet::new;
        Map<String,Set<String>> countryNamesByContinent =
         worldDao.findAllCountries()
                .stream()
                .collect(Collectors
                .groupingBy(Country::getContinent,
Collectors.mapping(Country::getName,Collectors.toCollection(defaultConstructorOfTreeSet)))
                 );
        Consumer<Map.Entry> printEntry =
                entry -> System.out.println(String.format("%s: %s",entry.getKey(),entry.getValue()));
        countryNamesByContinent.entrySet().forEach(printEntry);

    }
}
İşte kıtalardaki ülkelerin adlarından oluşan, bu kez sözlük sırasına göre sıralanmış listesi:
South America: [Argentina, Bolivia, Brazil, Chile, Colombia, Ecuador, Falkland Islands, French Guiana, Guyana, Paraguay, Peru, Suriname, Uruguay, Venezuela]
Asia: [Afghanistan, Armenia, Azerbaijan, Bahrain, Bangladesh, Bhutan, Brunei, Cambodia, China, Cyprus, East Timor, Georgia, Hong Kong, India, Indonesia, Iran, Iraq, Israel, Japan, Jordan, Kazakstan, Kuwait, Kyrgyzstan, Laos, Lebanon, Macao, Malaysia, Maldives, Mongolia, Myanmar, Nepal, North Korea, Oman, Pakistan, Palestine, Philippines, Qatar, Saudi Arabia, Singapore, South Korea, Sri Lanka, Syria, Taiwan, Tajikistan, Thailand, Turkey, Turkmenistan, United Arab Emirates, Uzbekistan, Vietnam, Yemen]
Europe: [Albania, Andorra, Austria, Belarus, Belgium, Bosnia and Herzegovina, Bulgaria, Croatia, Czech Republic, Denmark, Estonia, Faroe Islands, Finland, France, Germany, Gibraltar, Greece, Holy See (Vatican City State), Hungary, Iceland, Ireland, Italy, Latvia, Liechtenstein, Lithuania, Luxembourg, Macedonia, Malta, Moldova, Monaco, Netherlands, Norway, Poland, Portugal, Romania, Russian Federation, San Marino, Slovakia, Slovenia, Spain, Svalbard and Jan Mayen, Sweden, Switzerland, Ukraine, United Kingdom, Yugoslavia]
Africa: [Algeria, Angola, Benin, Botswana, British Indian Ocean Territory, Burkina Faso, Burundi, Cameroon, Cape Verde, Central African Republic, Chad, Comoros, Congo, Congo, The Democratic Republic of the, C“te d?Ivoire, Djibouti, Egypt, Equatorial Guinea, Eritrea, Ethiopia, Gabon, Gambia, Ghana, Guinea, Guinea-Bissau, Kenya, Lesotho, Liberia, Libyan Arab Jamahiriya, Madagascar, Malawi, Mali, Mauritania, Mauritius, Mayotte, Morocco, Mozambique, Namibia, Niger, Nigeria, Rwanda, R‚union, Saint Helena, Sao Tome and Principe, Senegal, Seychelles, Sierra Leone, Somalia, South Africa, Sudan, Swaziland, Tanzania, Togo, Tunisia, Uganda, Western Sahara, Zambia, Zimbabwe]
Antarctica: [Antarctica, Bouvet Island, French Southern territories, Heard Island and McDonald Islands, South Georgia and the South Sandwich Islands]
North America: [Anguilla, Antigua and Barbuda, Aruba, Bahamas, Barbados, Belize, Bermuda, Canada, Cayman Islands, Costa Rica, Cuba, Dominica, Dominican Republic, El Salvador, Greenland, Grenada, Guadeloupe, Guatemala, Haiti, Honduras, Jamaica, Martinique, Mexico, Montserrat, Netherlands Antilles, Nicaragua, Panama, Puerto Rico, Saint Kitts and Nevis, Saint Lucia, Saint Pierre and Miquelon, Saint Vincent and the Grenadines, Trinidad and Tobago, Turks and Caicos Islands, United States, Virgin Islands, British, Virgin Islands, U.S.]
Oceania: [American Samoa, Australia, Christmas Island, Cocos (Keeling) Islands, Cook Islands, Fiji Islands, French Polynesia, Guam, Kiribati, Marshall Islands, Micronesia, Federated States of, Nauru, New Caledonia, New Zealand, Niue, Norfolk Island, Northern Mariana Islands, Palau, Papua New Guinea, Pitcairn, Samoa, Solomon Islands, Tokelau, Tonga, Tuvalu, United States Minor Outlying Islands, Vanuatu, Wallis and Futuna]

9. Ülkelerin, en az nüfusa ve en çok nüfusa sahip şehirlerini bulalım:
package com.example.stream;

import com.example.domain.City;
import com.example.domain.Country;

import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * Binnur Kurt (binnur.kurt@gmail.com)
 */
public class CountryCitySummaryStatistics implements Consumer<Country> {
    private City min;
    private City max;
    private long count;

    public CountryCitySummaryStatistics() {
    }

    @Override
    public void accept(Country country) {
        Supplier<CitySummaryStatistics> citySummaryStatisticsSupplier=
                () -> new CitySummaryStatistics((l,r)-> Long.compare(l.getPopulation(),r.getPopulation()));
        CitySummaryStatistics css= country.getCities().stream()
                .collect(citySummaryStatisticsSupplier,CitySummaryStatistics::accept,CitySummaryStatistics::combine);
        min= css.getMin();
        max= css.getMax();
        count= css.getCount();
    }

    public void combine(CountryCitySummaryStatistics other) {
    }

    public City getMin() {
        return min;
    }

    public void setMin(City min) {
        this.min = min;
    }

    public City getMax() {
        return max;
    }

    public void setMax(City max) {
        this.max = max;
    }

    public long getCount() {
        return count;
    }

    public void setCount(long count) {
        this.count = count;
    }

    @Override
    public String toString() {
        return "CountryCitySummaryStatistics{" +
                "min=" + getMin() +
                ", max=" + getMax() +
                ", count=" + getCount() +
                '}';
    }

}

package com.example.stream;

import com.example.domain.City;

import java.util.Comparator;
import java.util.function.Consumer;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class CitySummaryStatistics implements Consumer<City> {
    private Comparator<City> comparator;
    private City min;
    private City max;
    private long count;

    public CitySummaryStatistics() {
    }

    public CitySummaryStatistics(Comparator<City> comparator) {
        this.comparator = comparator;
    }

    @Override
    public void accept(City city) {
        count ++;
        min = min!=null && comparator.compare(min,city)<=0 ? min : city;
        max = max!=null && comparator.compare(max,city)>=0 ? max : city;
    }

    public void combine(CitySummaryStatistics other) {
        this.min= comparator.compare(this.min,other.min)<=0 ? this.min : other.min;
        this.max= comparator.compare(this.max,other.max)>=0 ? this.max : other.max;
    }

    public City getMin() {
        return min;
    }

    public void setMin(City min) {
        this.min = min;
    }

    public City getMax() {
        return max;
    }

    public void setMax(City max) {
        this.max = max;
    }

    public long getCount() {
        return count;
    }

    public void setCount(long count) {
        this.count = count;
    }

    @Override
    public String toString() {
        return "CitySummaryStatistics{" +
                "min=" + getMin() +
                ", max=" + getMax() +
                ", count=" + getCount() +
                '}';
    }

}

package com.example.exercises;

import com.example.dao.InMemoryWorldDao;
import com.example.dao.WorldDao;
import com.example.domain.Country;
import com.example.stream.CountryCitySummaryStatistics;

import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.stream.Collector;
import java.util.stream.Collectors;

/**
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class Exercise9 {

    public static void main(String[] args) {
        WorldDao worldDao = InMemoryWorldDao.getInstance();
        BiConsumer<CountryCitySummaryStatistics, Country> accumulator = (s, c) -> s.accept(c);
        BinaryOperator<CountryCitySummaryStatistics> combiner = (l, r) -> {
            l.combine(r);
            return l;
        };

        Map<String, CountryCitySummaryStatistics> countryCityStatistics =
                worldDao.findAllCountries()
                        .stream()
                        .collect(Collectors.groupingBy(Country::getCode,
                                Collector.of(CountryCitySummaryStatistics::new, accumulator, combiner)));
        Consumer<Map.Entry> printEntry =
                entry -> System.out.println(String.format("%s: %s", entry.getKey(), entry.getValue()));
        countryCityStatistics.entrySet().forEach(printEntry);

    }
}
İşte ülkelerin şehirlerinin durumu:
NZL: CitySummaryStatistics{min=City [id=3502, name=Lower Hutt, population=98100, countryCode=NZL], max=City [id=3494, name=Auckland, population=381800, countryCode=NZL], count=9}
FJI: CitySummaryStatistics{min=City [id=764, name=Suva, population=77366, countryCode=FJI], max=City [id=764, name=Suva, population=77366, countryCode=FJI], count=1}
PNG: CitySummaryStatistics{min=City [id=2884, name=Port Moresby, population=247000, countryCode=PNG], max=City [id=2884, name=Port Moresby, population=247000, countryCode=PNG], count=1}
GLP: CitySummaryStatistics{min=City [id=919, name=Basse-Terre, population=12433, countryCode=GLP], max=City [id=918, name=Les Abymes, population=62947, countryCode=GLP], count=2}
STP: CitySummaryStatistics{min=City [id=3172, name=SÆo Tom‚, population=49541, countryCode=STP], max=City [id=3172, name=SÆo Tom‚, population=49541, countryCode=STP], count=1}
WLF: CitySummaryStatistics{min=City [id=3536, name=Mata-Utu, population=1137, countryCode=WLF], max=City [id=3536, name=Mata-Utu, population=1137, countryCode=WLF], count=1}
MHL: CitySummaryStatistics{min=City [id=2507, name=Dalap-Uliga-Darrit, population=28000, countryCode=MHL], max=City [id=2507, name=Dalap-Uliga-Darrit, population=28000, countryCode=MHL], count=1}
CUB: CitySummaryStatistics{min=City [id=2426, name=Ciego de µvila, population=98505, countryCode=CUB], max=City [id=2413, name=La Habana, population=2256000, countryCode=CUB], count=14}
SDN: CitySummaryStatistics{min=City [id=3235, name=Juba, population=114980, countryCode=SDN], max=City [id=3224, name=Omdurman, population=1271403, countryCode=SDN], count=12}
GMB: CitySummaryStatistics{min=City [id=904, name=Banjul, population=42326, countryCode=GMB], max=City [id=903, name=Serekunda, population=102600, countryCode=GMB], count=2}
MYS: CitySummaryStatistics{min=City [id=2481, name=Shah Alam, population=102019, countryCode=MYS], max=City [id=2464, name=Kuala Lumpur, population=1297526, countryCode=MYS], count=18}
MYT: CitySummaryStatistics{min=City [id=2514, name=Mamoutzou, population=12000, countryCode=MYT], max=City [id=2514, name=Mamoutzou, population=12000, countryCode=MYT], count=1}
TWN: CitySummaryStatistics{min=City [id=3304, name=Miaoli, population=90000, countryCode=TWN], max=City [id=3263, name=Taipei, population=2641312, countryCode=TWN], count=42}
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
BRA: CitySummaryStatistics{min=City [id=455, name=µguas Lindas de Goi s, population=89200, countryCode=BRA], max=City [id=206, name=SÆo Paulo, population=9968485, countryCode=BRA], count=250}
BRB: CitySummaryStatistics{min=City [id=174, name=Bridgetown, population=6070, countryCode=BRB], max=City [id=174, name=Bridgetown, population=6070, countryCode=BRB], count=1}
TUV: CitySummaryStatistics{min=City [id=3424, name=Funafuti, population=4600, countryCode=TUV], max=City [id=3424, name=Funafuti, population=4600, countryCode=TUV], count=1}
DEU: CitySummaryStatistics{min=City [id=3160, name=Esslingen am Neckar, population=89667, countryCode=DEU], max=City [id=3068, name=Berlin, population=3386667, countryCode=DEU], count=93}
LVA: CitySummaryStatistics{min=City [id=2436, name=Liepaja, population=89439, countryCode=LVA], max=City [id=2434, name=Riga, population=764328, countryCode=LVA], count=3}
EGY: CitySummaryStatistics{min=City [id=644, name=Disuq, population=91300, countryCode=EGY], max=City [id=608, name=Cairo, population=6789479, countryCode=EGY], count=37}
JAM: CitySummaryStatistics{min=City [id=1531, name=Portmore, population=99799, countryCode=JAM], max=City [id=1529, name=Spanish Town, population=110379, countryCode=JAM], count=3}
NIU: CitySummaryStatistics{min=City [id=2805, name=Alofi, population=682, countryCode=NIU], max=City [id=2805, name=Alofi, population=682, countryCode=NIU], count=1}
ZAF: CitySummaryStatistics{min=City [id=755, name=Ladysmith, population=89292, countryCode=ZAF], max=City [id=712, name=Cape Town, population=2352121, countryCode=ZAF], count=44}
VIR: CitySummaryStatistics{min=City [id=4067, name=Charlotte Amalie, population=13000, countryCode=VIR], max=City [id=4067, name=Charlotte Amalie, population=13000, countryCode=VIR], count=1}
HND: CitySummaryStatistics{min=City [id=935, name=La Ceiba, population=89200, countryCode=HND], max=City [id=933, name=Tegucigalpa, population=813900, countryCode=HND], count=3}
BRN: CitySummaryStatistics{min=City [id=538, name=Bandar Seri Begawan, population=21484, countryCode=BRN], max=City [id=538, name=Bandar Seri Begawan, population=21484, countryCode=BRN], count=1}

10. Dünya ülkelerinin Gayri Safi Mill Hasıla değerlerinin, minimum, maksimum, ortalama ve standard sapma değerlerini hesaplayalım. Aslında bu hesaplama DoubleSummaryStatistics yardımıyla çok kolay hesaplanabilirdi. Ancak bu sınıf bize standard sapma değerini vermiyor. Bu nedenle DoubleSummaryStatistics sınıfından standard sapma değerini de hesaplayacak yeni bir sınıf türeteceğiz: DoubleSummaryGaussianStatistics. Ancak hala bir problemimiz var. Stream API kullandığımız için hesaplamayı tek taramada gerçekleştirmemiz gerekir. Bunun için standard sapma hesabı için tek geçişli bir algoritmaya ihtiyacımız bulunuyor:
Standard sapmayı ise Qk'ya bağlı olarak aşağıdaki şekilde hesaplayabiliriz:
package com.example.stream;

import java.util.DoubleSummaryStatistics;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class DoubleSummaryGaussianStatistics extends DoubleSummaryStatistics {
    private double variance;
    private double stdVariance;
    private double Mk;
    private double Qk;

    @Override
    public void accept(double value) {
        super.accept(value);
        if (1 == getCount()) {
            Mk = value;
            Qk = 0.;
        } else {
            double difference = value - Mk;
            Mk += difference/getCount();
            Qk += ((getCount()-1)*difference*difference)/getCount();
        }
    }

    @Override
    public void combine(DoubleSummaryStatistics other) {
        super.combine(other);
    }

    public double getVariance() {
        variance= Qk / (getCount() - 1);
        return variance;
    }

    public double getStdVariance() {
        stdVariance= Math.sqrt (Qk/getCount());
        return stdVariance;
    }

    @Override
    public String toString() {
        return "DoubleSummaryGaussianStatistics{" +
                "variance=" + getVariance() +
                ", stdVariance=" + getStdVariance() +
                "}\n"+super.toString();
    }
}

package com.example.exercises;

import com.example.dao.InMemoryWorldDao;
import com.example.dao.WorldDao;
import com.example.domain.Country;
import com.example.stream.DoubleSummaryGaussianStatistics;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class Exercise10 {

    public static void main(String[] args) {
        WorldDao worldDao = InMemoryWorldDao.getInstance();
        DoubleSummaryGaussianStatistics gnpStatistics =
           worldDao.findAllCountries()
                   .stream()
                   .mapToDouble(Country::getGnp)
                   .collect(
                           DoubleSummaryGaussianStatistics::new,
                           DoubleSummaryGaussianStatistics::accept,
                           DoubleSummaryGaussianStatistics::combine
                   );
        System.out.println(gnpStatistics);
    }
}
İşte dünyanın GSMH istatistikleri:
DoubleSummaryGaussianStatistics{variance=4.0704091053847986E11, stdVariance=636661.4567369269}
DoubleSummaryGaussianStatistics{count=239, sum=29354907.900000, min=0.000000, average=122823.882427, max=8510700.000000}

No comments:

Post a Comment