由于超级灵活和方便,我一直在使用很多Perl哈希。 例如,在Perl中,我可以执行以下操作:
$hash{AREA_CODE}->{PHONE}->{STREET_ADDR}
我想知道如何用Java完成同样的事情,我想这与HashMap有关?
谢谢,
答案 0 :(得分:18)
由于超级灵活和方便,我一直在使用很多Perl哈希。例如,在Perl中我可以执行以下操作:
$hash{AREA_CODE}->{PHONE}->{STREET_ADDR}
我想知道如何用Java完成同样的事情,我想这与HashMap有关?
近似以下Perl代码的Java代码:
my %hash;
$hash{AREA_CODE}{PHONE}{STREET_ADDR} = "221B Baker Street";
printf "Street address is %s\n", $hash{AREA_CODE}{PHONE}{STREET_ADDR};
是
HashMap<String, HashMap<String, HashMap<String, String>>> hash =
new HashMap<String, HashMap<String, HashMap<String, String>>>();
hash.put("AREA_CODE", new HashMap<String, HashMap<String, String>>());
hash.get("AREA_CODE").put("PHONE", new HashMap<String, String>());
hash.get("AREA_CODE").get("PHONE").put("STREET_ADDR", "221B Baker Street");
System.out.printf("Street address is %s\n",
hash.get("AREA_CODE").get("PHONE").get("STREET_ADDR"));
那不是特别吗? :)
我说'近似'有很多原因。其中之一就是在Java中,你只会因为想要在Java的下一行上完成相当于这个非常直接的Perl代码而对极端中风这一点感到沮丧:
$hash{AREA_CODE}{PREFIX} = 800;
如果你想要Perl在这样的事情上的灵活性和便利性,Java根本就不会给你。更糟糕的是,它的党派通常会因为表达这种愿望而谴责你。
答案 1 :(得分:5)
请注意Java没有Perl的自动生成(方便但dangerous功能),以便
hash.get("areaCode").get("phone").get("streetAdr")
如果例如get(phone)返回null,将抛出异常。 还要注意你不应该为具有固定名称(“属性”)的东西使用哈希,你应该用它的getter和setter定义你自己的类。
答案 2 :(得分:5)
首先,您的具体示例($hash{AREA_CODE}->{PHONE}->{STREET_ADDR}
),使用硬编码字符串作为哈希键,并不像Michael Carman所指出的那样在Java中真正有用的数据结构 - 它应该存储为一个类属性(说实话,它在概念上是一个糟糕的数据结构 - 像这样的数据更可能是一组手机,而不是手机的哈希)。
其次,假设你实际上意味着$hash{$AREA_CODE}->{$PHONE}->{$STREET_ADDR}
,看起来每个人的Java代码到目前为止都没有实现通用的等效代码 - 代码都假设Java哈希是为了存储示例而新初始化的,或者是完全填充的,用于检索示例(换句话说,正如 leonbloy 的回答所指出的那样,缺少自动修复功能)。
正确的代码mimiquing autovivification是:
// This method will ensure that hash-of-hash-of-hashes structure exists of a given set of 3 keys.
public HashMap<String, HashMap<String, HashMap<String, Object>>>
autovivification_3rd_level (
HashMap<String, HashMap<String, HashMap<String, Object>>> hash
, String AREA_CODE, String PHONE, String STREET_ADDR) {
if (hash == null) {
hash = new HashMap<String, HashMap<String, HashMap<String, Object>>>();
}
if (!hash.contains(AREA_CODE) || hash.get(AREA_CODE) == null) {
hash.put(new HashMap<String, HashMap<String, Object>>());
}
HashMap<String, HashMap<String, Object>> AREA_CODE_hash
= (HashMap<String, HashMap<String, Object>>) hash.get(AREA_CODE);
if (!AREA_CODE_hash.contains(PHONE) || AREA_CODE_hash.get(PHONE) == null) {
AREA_CODE_hash.put(new HashMap<String, Object>());
}
return hash;
}
////////////////////////////////////////////////////////////////////////////////////
// Equivalent to Perl's "$hash{$AREA_CODE}->{$PHONE}->{$STREET_ADDR} = value;"
public Object put_3d_level_hash(
HashMap<String, HashMap<String, HashMap<String, Object>>> hash
, String AREA_CODE, String PHONE, String STREET_ADDR,
, Object value) {
hash = autovivification_3rd_level(hash, AREA_CODE, PHONE, STREET_ADDR);
return hash.get(AREA_CODE).get(PHONE).put(STREET_ADDR, value);
}
put_3d_level_hash(hash, AREA_CODE, PHONE, STREET_ADDR, obj);
////////////////////////////////////////////////////////////////////////////////////
// Equivalent to Perl's "$var = $hash{$AREA_CODE}->{$PHONE}->{$STREET_ADDR}"
public Object get_3d_level_hash(HashMap<String, HashMap<String, HashMap<String, Object>>> hash
, String AREA_CODE, String PHONE, String STREET_ADDR) {
hash = autovivification_3rd_level(hash, AREA_CODE, PHONE, STREET_ADDR);
return hash.get(AREA_CODE).get(PHONE).get(STREET_ADDR);
}
Object obj = get_3d_level_hash(hash, AREA_CODE, PHONE, STREET_ADDR);
答案 3 :(得分:2)
Java有哈希,但由于强类型,它们不像Perl中的哈希那么灵活。多维哈希更难以使用。在Perl中,您可以声明一个哈希并让autovivification根据需要创建嵌套哈希。
my %hash;
$hash{a}{b} = 1;
在Java中,你必须预先声明它是哈希哈希。
Map<String,Map<String,Integer>> hash = new HashMap<String,HashMap<String,Integer>>();
hash.put("a", new HashMap<String, Integer>());
hash.get("a").put("b", new Integer(1));
对于每个额外的维度,您需要在声明中添加另一个Map<K,V>
嵌套。除了单调乏味之外,这还不是很好。
答案 4 :(得分:1)
如果哈希键是常量,为什么不hash.getAreaCode().getPhone().getStreetAddr()
呢?请记住,您的getter或构造函数都需要处理默认值生成。
答案 5 :(得分:1)
您可以轻松地对哈希进行子类化,以添加一个为您自动生成的方法。
来自:$hash{AREA_CODE}->{PHONE}->{STREET_ADDR}
收件人:hash.vivifyingGet(areaCode).put(phone, streetAddr)
。
假设我用:
创建了哈希/**
* A two-level autovivifying hashmap of X and Y to Z. Provides
* a new method #vivifyingGet(X) which creates the next level of hash.
*/
Map<AreaCode, Map<Phone, StreetAddr>> hash =
new HashMap<AreaCode, Map<Phone, StreetAddr>>() {
/**
* Convenience method to get or create the next level of hash.
* @param key the first level key
* @return the next level map
*/
public Map<Phone, StreetAddr> vivifyingGet(Phone key) {
if (containsKey(key)) {
return get(key);
} else {
Map<Phone, StreetAddr> = hash = new HashMap<Phone, StreetAddr>();
put(key, hash);
return hash;
}
}
};
答案 6 :(得分:0)
我在工作中错过了很多perl哈希,并使用哈希类做了一些丑陋的变通办法。
上周我有一个想法在一个PerlMap
类中实现整个事情,它使用分隔符来访问对象,最重要的是Lists
zu访问子集。
它适用于map.get(code:street:phone)
和map.put(code:street:phone,"123456789")
。要获取phonenumber列表,只需使用map.getList(code:street)
即可。
我刚刚开始,但现在在我的项目中使用。它没有复杂性的限制:-)你可以选择免费的分隔符。我将所有内容放在http://www.jdeer.org下。玩得开心。
答案 7 :(得分:-4)
如果你想要这种灵活性但仍然在JVM中运行,你可能会想要使用Groovy。 tchrist喜欢忽略Java强类型而不是像Perl或PHP这样的动态类型语言 - 并且也喜欢忽略Java在运行时速度快一个数量级,但这只是我的“党派”,显然。