user12361681
user12361681

Reputation: 107

Java - Create a List of Objects

I'm creating a function that stores the List of Countries with the Code, Name and Flag (Image byte[]).

There are about 250 countries and even though my method only runs once, it seems highly inefficient.

This is a Maven Spring Project and the images are being loaded from /src/main/resources/images/flags

private void defaultCountries() throws IOException {
    List<Country> countries = new ArrayList<>();
    countries.add(new Country("AF", "Afghanistan", Files.readAllBytes(Paths.get("/images/flags/af.png"))));
    ... // All 250 countries
}

I'm copying the information from here manually https://github.com/yusufshakeel/mysql-country-with-flag

Can someone help me improve this?

Thanks

Upvotes: 2

Views: 95

Answers (2)

Mark Storer
Mark Storer

Reputation: 15868

Your application is almost certainly "IO Bound", meaning that file IO (input/output) is slowing you down the most. There's only so much you can do, but there is at least one thing:

I suggest you put all your country flags in a single zip (uncompressed perhaps).

A non-trivial portion of file IO time is operating system overhead switching from one file to another. By assembling everything into a single file, you remove this overhead entirely. You'd then read in the zip, and pull out the individual parts you needed to build your images. Zip libraries have functions for accessing files within them, and Java's built-in zip handling is no different. Each zip entry has a name and a comment, so you might even be able to embed all your info into the entries and turn them into a little database.

I strongly recommend against hard-coding all the constants into your source and just reading out the images from equally hard-coded paths. It might work for this assignment. It might even be acceptable to your teacher. It is a terrible habit to get into if you want to be a professional programmer.

Upvotes: 2

y_ug
y_ug

Reputation: 1124

I'd use linked hash map as a container and java.util.Locale to get information about country:

    private HashMap<String,Country> defaultCountries() {
        return countriesWithFlags().collect(
                LinkedHashMap::new,
                (map,c) ->  {try {
                    map.put(c[0], new Country(c[0], c[1], Files.readAllBytes(Paths.get(c[2]))));
                } catch (IOException ignore) {}},
                LinkedHashMap::putAll
        );
    }

    private Stream<String[]> countriesWithFlags() {
        return Arrays.stream(Locale.getISOCountries()).map(iso -> new Locale("", iso))
                .map(l -> new String[]{
                        l.getCountry(),
                        l.getDisplayCountry(),
                        String.format("/images/flags/%s.png", l.getDisplayCountry().toLowerCase())
                });
    }

Unit test for countriesWithFlags:

package example;

import org.junit.Test;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

public class ContryCodesTest {
    final static Logger LOGGER = Logger.getLogger(ContryCodesTest.class.getName());

    public static class Country{
        public Country(String iso, String name, byte[] image) {
            // FIXME
        }
    }

    private HashMap<String,Country> defaultCountries() {
        return countriesWithFlags().collect(
                LinkedHashMap::new,
                (map,c) ->  {try {
                    map.put(c[0], new Country(c[0], c[1], Files.readAllBytes(Paths.get(c[2]))));
                } catch (IOException ignore) {}},
                LinkedHashMap::putAll
        );
    }

    private Stream<String[]> countriesWithFlags() {
        return Arrays.stream(Locale.getISOCountries()).map(iso -> new Locale("", iso))
                .map(l -> new String[]{
                        l.getCountry(),
                        l.getDisplayCountry(),
                        String.format("/images/flags/%s.png", l.getDisplayCountry().toLowerCase())
                });
    }

    @Test public void test() {
        List<String[]> cwfs = countriesWithFlags().collect(Collectors.toList());
        assertThat(cwfs, hasSize(250));
        assertThat(cwfs.get(cwfs.size()-1)[2], equalTo("/images/flags/zimbabwe.png"));
    }
}

Upvotes: 1

Related Questions