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

发布于 2024-07-15 20:05:32 字数 362 浏览 8 评论 0原文

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

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

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

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

I want to have a List or Array of some sort, storing this information about each country:

  • 2 letter code
  • Country name such as Brazil
  • Continent/region of the world such as Eastern Europe, North America, etc.

I will classify each country into the region/continent manually (but if there exists a way to do this automatically, do let me know). This question is about how to store and access the countries. For example, I want to be able to retrieve all the countries in North America.

I don't want to use local text files or such because this project will be converted to javascript using Google Web Toolkit. But storing in an Enum or another resource file of some sort, keeping it separate from the rest of the code, is what I'm really after.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

不必你懂 2024-07-22 20:05:32

只需创建一个名为 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> 或 Multimap 实现,例如来自 Apache commons 的 Multimap 实现。

Just make an enum called Country. Java enums can have properties, so there's your country code and name. For the continent, you pobably want another enum.

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;
    }
}

As for storing and access, one Map for each of the fields you'll be searching for, keyed on that that field, would be the standard solution. Since you have multiple values for the continent, you'll either have to use a Map<?, List<Country>>, or a Multimap implementation e.g. from Apache commons.

寄与心 2024-07-22 20:05:32

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 网站)许可证即可。

There is 246 countries in ISO 3166, you might get a relay big enum on back of this. I prefer to use XML file with list of countries, you can download one from http://www.iso.org/ and load them (e.g. when app is starting).
Than, as you need them in GWT load them in back as RPC call, but remember to cache those (some kind of lazy loading) so you wont finish with loading them each time.
I think this would be anyway better than holding them in code, as you will finish with loading full list each time module is accessed, even if user will not need to use this list.

So you need something which will hold country:

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();
    }
}

For GWT this class would need to implement IsSerializable.
And you can load those, on server side using:

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);
    }
}

Of course, if you need to find country by ISO 2 letter code you might wont to change List to Map probably.
If, as you mentioned, you need separate countries by continent, you might extend XML from ISO 3166 and add your own elements. Just check their (ISO website) license.

原谅过去的我 2024-07-22 20:05:32

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

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

If you frequently need to do a lookup by continent, I'd simply make a series of immutable lists, one for each continent, and populate them accordingly. The list of country-data for a continent is probably not going to change frequently enough for the cost of rebuilding such an array to be rebuilt when something needs to be altered.

Also, if you're willing to do the country-continent classification manually, the rest is automatic and can be done programmatically.

千纸鹤 2024-07-22 20:05:32

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

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

有关详细信息,请参阅 XStream 教程

The easiest way to do this is to create the country/continent structure in Java using a map (or whatever collection) and then persist it using XStream

This will create an XML representation of the collection, and you can read than into your process very easily and convert it back to the same collection type that you initially created. Furthermore, because it's XML, you can easily edit it outside of code. i.e. just in a text editor.

See the XStream tutorial for more info.

相思故 2024-07-22 20:05:32

使用 Locale 对象是我能想到的最好的解决方案,您不需要存储任何内容。
但是,如果您使用 GWT 尝试在服务器端执行此操作,正如有人所说,您将无法使其在客户端正常工作(因为它被翻译为 javascript),您可以按照所述通过 RPC 将它们发送到客户端前。

using the Locale object is the best solution I can think of, you wouldn't need to store anything.
But if you are using GWT try to do that on the server side, as some say you won't get it working correctly on the client side (as it gets translated to javascript) you can send them to the client in an RPC as stated before.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文