Лучший способ хранить коды стран, имена и континент в Java - PullRequest
7 голосов
/ 03 апреля 2009

Я хочу иметь List или Array некоторого вида, хранящий эту информацию о каждой стране:

  • 2-буквенный код
  • Название страны, например, Бразилия
  • Континент / регион мира, такой как Восточная Европа, Северная Америка и т. Д.

Я классифицирую каждую страну по региону / континенту вручную (но, если есть способ сделать это автоматически, дайте мне знать). Этот вопрос о том, как хранить и получить доступ к странам. Например, я хочу иметь возможность найти все страны Северной Америки.

Я не хочу использовать локальные текстовые файлы или что-то подобное, потому что этот проект будет конвертирован в javascript с помощью Google Web Toolkit. Но то, что я действительно хочу - это хранить в Enum или каком-либо другом файле ресурсов, отделив его от остального кода.

Ответы [ 5 ]

14 голосов
/ 03 апреля 2009

Просто сделайте перечисление под названием Country. Перечисления Java могут иметь свойства, поэтому есть код и имя вашей страны. Для континента вы, возможно, захотите еще один список.

public enum Continent
{
    AFRICA, ANTARCTICA, ASIA, AUSTRALIA, EUROPE, NORTH_AMERICA, SOUTH_AMERICA
}

public enum Country
{
    ALBANIA("AL", "Albania", Continent.EUROPE),
    ANDORRA("AN", "Andorra", Continent.EUROPE),
    ...

    private String code;
    private String name;
    private Continent continent;

    // get methods go here    

    private Country(String code, String name, Continent continent)
    {
        this.code = code;
        this.name = name;
        this.continent = continent;
    }
}

Что касается хранения и доступа, то одним из стандартных решений будет одна Карта для каждого из полей, которые вы будете искать, и с указанием этого поля. Поскольку у вас есть несколько значений для континента, вам придется либо использовать Map<?, List<Country>>, либо реализацию Multimap, например от Apache Commons.

5 голосов
/ 03 апреля 2009

В ISO 3166 есть 246 стран, вы можете получить большое количество перечислений. Я предпочитаю использовать XML-файл со списком стран, вы можете загрузить его из http://www.iso.org/ и загрузить его (например, при запуске приложения). Затем, когда они вам понадобятся в GWT, загрузите их обратно как вызов RPC, но не забывайте кэшировать их (какая-то ленивая загрузка), чтобы не заканчивать их загрузку каждый раз. Я думаю, что это было бы в любом случае лучше, чем держать их в коде, так как вы закончите с загрузкой полного списка при каждом доступе к модулю, даже если пользователю не нужно будет использовать этот список.

Итак, вам нужно что-то, что будет содержать страну:

public class Country
{
    private final String name;
    private final String code;

    public Country(String name, String code)
    {
        this.name = name;
        this.code = code;
    }

    public String getName()
    {
        return name;
    }

    public String getCode()
    {
        return code;
    }

    public boolean equals(Object obj)
    {
        if (this == obj)
        {
            return true;
        }
        if (obj == null || getClass() != obj.getClass())
        {
            return false;
        }

        Country country = (Country) obj;

        return code.equals(country.code);
    }

    public int hashCode()
    {
        return code.hashCode();
    }
}

Для GWT этот класс должен реализовывать IsSerializable. И вы можете загрузить их на стороне сервера, используя:

import java.util.ArrayList;
import java.util.List;
import java.io.InputStream;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class CountriesService
{
    private static final String EL_COUNTRY = "ISO_3166-1_Entry";
    private static final String EL_COUNTRY_NAME = "ISO_3166-1_Country_name";
    private static final String EL_COUNTRY_CODE = "ISO_3166-1_Alpha-2_Code_element";
    private List<Country> countries = new ArrayList<Country>();

    public CountriesService(InputStream countriesList)
    {
        parseCountriesList(countriesList);
    }

    public List<Country> getCountries()
    {
        return countries;
    }

    private void parseCountriesList(InputStream countriesList)
    {
        countries.clear();
        try
        {
            Document document = parse(countriesList);
            Element root = document.getRootElement();
            //noinspection unchecked
            Iterator<Element> i = root.elementIterator(EL_COUNTRY);
            while (i.hasNext())
            {
                Element countryElement = i.next();
                Element countryName = countryElement.element(EL_COUNTRY_NAME);
                Element countryCode = countryElement.element(EL_COUNTRY_CODE);

                String countryname = countryName.getText();
                countries.add(new Country(countryname, countryCode.getText()));
            }
        }
        catch (DocumentException e)
        {
            log.error(e, "Cannot read countries list");
        }
        catch (IOException e)
        {
            log.error(e, "Cannot read countries list");
        }
    }

    public static Document parse(InputStream inputStream) throws DocumentException
    {
        SAXReader reader = new SAXReader();
        return reader.read(inputStream);
    }
}

Конечно, если вам нужно найти страну по буквенному коду ISO 2, вы, возможно, захотите изменить Список на Карту, вероятно. Если, как вы упомянули, вам нужны отдельные страны по континентам, вы можете расширить XML с ISO 3166 и добавить свои собственные элементы. Просто проверьте их (ISO сайт) лицензию.

4 голосов
/ 03 апреля 2009

Если вам часто требуется выполнить поиск по континентам, я просто составил бы ряд неизменных списков, по одному для каждого континента, и заполнил бы их соответствующим образом. Список страновых данных для континента, вероятно, не будет меняться достаточно часто, чтобы затраты на восстановление такого массива можно было перестроить, когда что-то потребуется изменить.

Кроме того, если вы хотите выполнить классификацию страны-континента вручную, все остальное выполняется автоматически и может быть выполнено программно.

  • Используйте Locale.getISOCountries(), чтобы получить список кодов стран.
  • Используйте Locale.getDisplayCountry(), чтобы получить отображаемое название каждой страны.
2 голосов
/ 03 апреля 2009

Самый простой способ сделать это - создать структуру страны / континента в Java с использованием карты (или любой другой коллекции), а затем сохранить ее, используя XStream

Это создаст XML-представление коллекции, и вы сможете очень легко прочитать ее в свой процесс и преобразовать ее обратно в тот же тип коллекции, который вы изначально создали. Кроме того, поскольку это XML, вы можете легко редактировать его вне кода. то есть просто в текстовом редакторе.

Для получения дополнительной информации см. Учебник XStream .

0 голосов
/ 19 января 2012

использование объекта Locale - лучшее решение, которое я могу придумать, вам не нужно ничего хранить. Но если вы используете GWT, попробуйте сделать это на стороне сервера, поскольку некоторые говорят, что вы не получите правильную работу на стороне клиента (так как он переводится в javascript), вы можете отправить их клиенту в RPC, как указано до этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...