javalambdajava-8java-stream

How to call a function inside Stream.map()


I am using java.util.Locale to get a list of countries.

I have code that looks like this:

List<Country> countries = new ArrayList<>();

String[] countryCodes = Locale.getISOCountries();

for (String countryCode : countryCodes) {
    Locale locale = new Locale(language, countryCode);
    String code = locale.getCountry();
    String name = locale.getDisplayCountry(locale);

    try {
        countries.add(new Country(code, name));
    } catch (IllegalArgumentException e) {
        // code and name not valid for creating country. ignore
    }
}

return countries;

And it works fine. I would like to convert this code that I have in using Java Streams.

I have started like this:

return Stream.of(Locale.getISOCountries())
                .map(countryCode -> new Locale(language, countryCode))
                .map(c-> new Country(c.getCountry(), c.getDisplayCountry()))
                .filter(c-> !(c.getCode().equals("")) && !(c.getName().equals("")))
                .collect(Collectors.toList());

But instead of this line of code

.map(c-> new Country(c.getCountry(), c.getDisplayCountry()))

I would like to call this function:

private Optional<Country> createCountry(Locale locale) {
    try {
        return Optional.of(new Country(locale.getCountry(), locale.getDisplayCountry(locale)));
    } catch (IllegalArgumentException e) {
        return Optional.empty();
    }
}

I was thinking in doing something like this:

.map(createCountry(locale))

But the function and locale are not recognized.

What am I missing?


Solution

  • The map method accepts a Function while you are providing it with the result of the method invocation, which is an Optional<Country>. You need to pass in the method reference instead:

    List<Country> countries = Stream.of(Locale.getISOCountries())
                .map(countryCode -> new Locale(language, countryCode))
                .map(this::createCountry)
                .filter(Optional::isPresent)
                .map(Optional::get)
                .filter(c -> !(c.getCode().equals("")) && !(c.getName().equals("")))
                .collect(Collectors.toList());
    

    Note the additional steps to map the Optional to a Country if present.