在Java中存储国家/地区代码,名称和Continent的最佳方式

时间:2009-04-03 12:12:27

标签: java arrays linked-list hashmap treemap

我想要某种ListArray,存储有关每个国家/地区的信息:

  • 2个字母代码
  • 国家名称,如巴西
  • 东欧,北美等世界大陆/地区

我会手动将每个国家/地区分类到地区/大陆(但如果有办法自动执行此操作,请告诉我)。这个问题是关于如何存储和访问这些国家。例如,我希望能够检索北美的所有国家。

我不想使用本地文本文件等,因为这个项目将使用Google Web Toolkit转换为javascript。但是存储在Enum或其他某种资源文件中,与其他代码分开,就是我真正想要的。

5 个答案:

答案 0 :(得分:14)

只需制作一个名为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,键入该字段,将成为标准解决方案。由于您有非洲大陆的多个值,因此您必须使用Map<?, List<Country>>或Multimap实施,例如来自Apache commons。

答案 1 :(得分:5)

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字母代码查找国家/地区,您可能不会将列表更改为地图。 如果您按照提到的那样,按大陆需要单独的国家/地区,则可以从ISO 3166扩展XML并添加自己的元素。只需检查他们的(ISO网站)许可证。

答案 2 :(得分:4)

如果您经常需要按洲洲进行查找,我只需制作一系列不可变列表,每个大陆一个,并相应地填充它们。一个大陆的国家数据列表可能不会经常变化,以便在需要改变某些东西时重建这样一个阵列的成本。

此外,如果您愿意手动进行国家/地区分类,其余部分是自动的,可以通过编程方式完成。

答案 3 :(得分:2)

最简单的方法是使用地图(或任何集合)在Java中创建country / continent结构,然后使用XStream

继续保存它

这将创建集合的XML表示形式,您可以非常轻松地读取进程并将其转换回最初创建的相同集合类型。此外,因为它是XML,您可以在代码之外轻松编辑它。即只是在文本编辑器中。

有关详细信息,请参阅XStream tutorial

答案 4 :(得分:0)

使用Locale对象是我能想到的最佳解决方案,您不需要存储任何东西。 但是,如果您正在使用GWT尝试在服务器端执行此操作,正如有人说您将无法在客户端上正常工作(因为它被转换为javascript),您可以在RPC中将它们发送到客户端之前。