在Java中存储国家代码、名称和大陆的最佳方法

在Java中存储国家代码、名称和大陆的最佳方法,java,arrays,linked-list,hashmap,treemap,Java,Arrays,Linked List,Hashmap,Treemap,我想要一个某种列表或数组,存储每个国家的信息: 2字母代码 国家名称,如巴西 世界大陆/地区,如东欧、北美等 我将手动将每个国家划分为区域/大陆(但如果有自动分类的方法,请告诉我)。这个问题是关于如何存储和访问这些国家。例如,我希望能够检索北美的所有国家 我不想使用本地文本文件,因为这个项目将使用GoogleWebToolkit转换为javascript。但我真正想要的是存储在枚举或其他某种资源文件中,使其与代码的其余部分分开。如果您经常需要按大陆进行查找,我只需为每个大陆创建一系列不可变列

我想要一个某种
列表
数组
,存储每个国家的信息:

  • 2字母代码
  • 国家名称,如巴西
  • 世界大陆/地区,如东欧、北美等
我将手动将每个国家划分为区域/大陆(但如果有自动分类的方法,请告诉我)。这个问题是关于如何存储和访问这些国家。例如,我希望能够检索北美的所有国家


我不想使用本地文本文件,因为这个项目将使用GoogleWebToolkit转换为javascript。但我真正想要的是存储在枚举或其他某种资源文件中,使其与代码的其余部分分开。

如果您经常需要按大陆进行查找,我只需为每个大陆创建一系列不可变列表,并相应地填充它们。一个大陆的国家数据列表可能不会频繁变化,以至于在需要更改某些内容时,重建这样一个阵列的成本无法重建

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

  • 用于获取国家/地区代码列表
  • 用于获取每个国家/地区的显示名称

只需创建一个名为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;
    }
}

至于存储和访问,标准解决方案是为您要搜索的每个字段创建一个映射,并键入该字段。由于该大陆有多个值,您必须使用
地图ISO 3166中有246个国家,您可能会在后面得到一个中继大枚举。我更喜欢将XML文件与国家列表一起使用,您可以从中下载并加载它们(例如,当应用程序启动时)。
然后,当您需要在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);
    }
}
import java.util.ArrayList;
导入java.util.List;
导入java.io.InputStream;
导入org.dom4j.Attribute;
导入org.dom4j.Document;
导入org.dom4j.DocumentException;
导入org.dom4j.Element;
导入org.dom4j.io.SAXReader;
公共类国家服务
{
私有静态最终字符串EL_COUNTRY=“ISO_3166-1_Entry”;
私有静态最终字符串EL_COUNTRY_NAME=“ISO_3166-1_COUNTRY_NAME”;
私有静态最终字符串EL_COUNTRY_CODE=“ISO_3166-1_Alpha-2_CODE_元素”;
私有列表国家=新的ArrayList();
公共国家服务(输入流国家列表)
{
parseCountriesList(countriesList);
}
国家/地区公共列表()
{
返回国;
}
私有void parseCountriesList(InputStream countriesList)
{
国家。清除();
尝试
{
文档=解析(countriesList);
元素根=document.getRootElement();
//未检查
迭代器i=root.element迭代器(EL_国家);
while(i.hasNext())
{
元素countryElement=i.next();
Element countryName=countryElement.Element(EL_COUNTRY_NAME);
元素countryCode=countryElement.Element(EL_国家代码);
字符串countryname=countryname.getText();
添加(新国家(countryname,countryCode.getText());
}
}
捕获(文档异常)
{
日志错误(e,“无法读取国家列表”);
}
捕获(IOE异常)
{
日志错误(e,“无法读取国家列表”);
}
}
公共静态文档解析(InputStream InputStream)引发DocumentException
{
SAXReader=新SAXReader();
返回reader.read(inputStream);
}
}
当然,若你们需要通过ISO2字母代码查找国家,你们可能不会将列表更改为地图。
如您所述,如果您需要按大陆划分不同的国家,您可以从ISO 3166扩展XML并添加您自己的元素。只需查看他们的(ISO网站)许可证。

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

这将创建集合的XML表示,您可以非常轻松地将其读入流程,并将其转换回最初创建的集合类型。此外,由于它是XML,您可以在代码之外轻松地编辑它。i、 只是在文本编辑器中


有关更多信息,请参阅。

使用Locale对象是我能想到的最佳解决方案,您不需要存储任何内容。
但是,如果您正在使用GWT,请尝试在服务器端这样做,正如有人说的那样,您将无法在客户端正确运行GWT(因为它被转换为javascript),您可以像前面所说的那样,通过RPC将它们发送到客户端。

不可变列表是什么意思?你能分享一些代码吗?对不起,我是Java的新手。不可变列表的内容是不能更改的(请参阅ReadOnlyCollection)。但是,我更喜欢Michael的方法,我认为你应该采用这种方法而不是我的方法。它们可以组合在一起:enum Country{…static{for(大陆c:Continental.values())for(Country cc:Country.values())if(cc.GetContinental()==c)ByContinental.get(c).add