Java 关联数组

Posted

技术标签:

【中文标题】Java 关联数组【英文标题】:Java associative-array 【发布时间】:2011-07-04 14:54:24 【问题描述】:

如何像在 php 中一样在 Java 中创建和获取关联数组?

例如:

$arr[0]['name'] = 'demo';
$arr[0]['fname'] = 'fdemo';
$arr[1]['name'] = 'test';
$arr[1]['fname'] = 'fname';

【问题讨论】:

【参考方案1】:

Java 不支持关联数组,但是这可以使用Map 轻松实现。例如,

Map<String, String> map = new HashMap<String, String>();
map.put("name", "demo");
map.put("fname", "fdemo");
// etc

map.get("name"); // returns "demo"

对您的示例更准确(因为您可以将 String 替换为任何满足您需要的对象)将声明:

List<Map<String, String>> data = new ArrayList<>();
data.add(0, map);
data.get(0).get("name"); 

See the official documentation for more information

【讨论】:

如果外部映射不包含条目 0 的映射,这将抛出 NullPointerException。 PHP 使用 $arr[0]['name'] 不是更宽容吗(我根本不懂这种语言)? 如果您尝试访问不存在的密钥,PHP 不会喜欢它,不 :) @edem,一些实施是必要的。 今天然而,由于(意外?)性能差异,在几乎所有情况下都更喜欢ArrayList。但这是另一个讨论。 永远不要忘记初始化确切的哈希大小并将负载因子设置为 1:HashMap(capacity, 1)。否则,您可能会实现巨大的开销,并且您的对象需要大量 RAM。为 ArrayList +1,但为什么不编辑答案? @Marcus "永远不要忘记初始化确切的哈希大小并将负载因子设置为 1" - 你从哪里得到这个建议?您几乎应该从不指定HashMap 的负载因子,当然不能没有有意地对行为进行基准测试并为您的用例找到更好的负载因子。指定初始大小的唯一原因是如果您事先知道地图将非常大。 HashMap 如果为空,则不会浪费(太多)内存,但如果您打算创建一个大地图,您可以通过预先指定其大小来保存多个数组调整大小。【参考方案2】:

Java 没有 PHP 那样的关联数组。

您正在做的事情有多种解决方案,例如使用地图,但这取决于您要如何查找信息。您可以轻松编写一个包含所有信息的类,并将它们的实例存储在 ArrayList 中。

public class Foo
    public String name, fname;

    public Foo(String name, String fname)
        this.name = name;
        this.fname = fname;
    

然后……

List<Foo> foos = new ArrayList<Foo>();
foos.add(new Foo("demo","fdemo"));
foos.add(new Foo("test","fname"));

所以你可以像...一样访问它们

foos.get(0).name;
=> "demo"

【讨论】:

我不明白,你如何在这里通过键访问东西,我认为这是拥有关联数组的要点。 @windmaomao 你没有。这就是为什么公认的答案是使用地图。 关联数组是动态且灵活的。可以在运行时添加新属性。一个Java类有一组预定义的实例变量,设置一个编译时间。【参考方案3】:

您可以通过地图完成此操作。像

Map<String, String>[] arr = new HashMap<String, String>[2]();
arr[0].put("name", "demo");

但是当您开始使用 Java 时,我相信您会发现,如果您创建一个代表您的数据的类/模型将是您的最佳选择。我会做的

class Person
String name;
String fname;

List<Person> people = new ArrayList<Person>();
Person p = new Person();
p.name = "demo";
p.fname = "fdemo";
people.add(p);

【讨论】:

我想我更喜欢这种方法,谢谢。来自一切都如此简单的php,使用java有点尴尬,但很好的解决方案。谢谢。 为什么使用 List 而不是 ArrayList?这里是一个java新手。 'List' 是一个抽象类,'ArrayList' 是该类的实现之一,还有其他类型的列表派生自同一个抽象类。因此,ArrayList 也是一个 List。您不能创建抽象类的实例,只需在此处将其用作类型,您需要为您的实例使用实现。所以List是类型,ArrayList是这里的实例。【参考方案4】:

查看Map 接口,以及具体类HashMap。

创建地图:

Map<String, String> assoc = new HashMap<String, String>();

添加键值对:

assoc.put("name", "demo");

要检索与键关联的值:

assoc.get("name")

当然,您可以创建一个地图数组,这似乎是您想要的:

Map<String, String>[] assoc = ...

【讨论】:

【参考方案5】:

Java 中没有关联数组这种东西。它最近的亲戚是Map,它是强类型的,但语法/API 不太优雅。

根据您的示例,这是您可以获得的最接近的值:

Map<Integer, Map<String, String>> arr = 
    org.apache.commons.collections.map.LazyMap.decorate(
         new HashMap(), new InstantiateFactory(HashMap.class));

//$arr[0]['name'] = 'demo';
arr.get(0).put("name", "demo");

System.out.println(arr.get(0).get("name"));
System.out.println(arr.get(1).get("name"));    //yields null

【讨论】:

LazyMap.decorateInstantiateFactory 是干什么用的? +1 所有其他答案似乎都假设“键”之一是整数。如果关联数组基于两个非整数键(我们会在 python 中说的元组)怎么办?我相信你需要使用这种方法,因为索引变得不可能。【参考方案6】:

我也在寻找关联数组,发现地图列表是最好的解决方案。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class testHashes 

public static void main(String args[])
    Map<String,String> myMap1 = new HashMap<String, String>();

    List<Map<String , String>> myMap  = new ArrayList<Map<String,String>>();

    myMap1.put("URL", "Val0");
    myMap1.put("CRC", "Vla1");
    myMap1.put("SIZE", "Vla2");
    myMap1.put("PROGRESS", "Vla2");

    myMap.add(0,myMap1);
    myMap.add(1,myMap1);

    for (Map<String, String> map : myMap) 
        System.out.println(map.get("URL"));
    

    //System.out.println(myMap);





【讨论】:

【参考方案7】:

Java equivalent of Perl's hash

HashMap<Integer, HashMap<String, String>> hash;

【讨论】:

【参考方案8】:

Java 没有关联数组,最接近的就是Map interface

这是该页面的示例。

import java.util.*;

public class Freq 
    public static void main(String[] args) 
        Map<String, Integer> m = new HashMap<String, Integer>();

        // Initialize frequency table from command line
        for (String a : args) 
            Integer freq = m.get(a);
            m.put(a, (freq == null) ? 1 : freq + 1);
        

        System.out.println(m.size() + " distinct words:");
        System.out.println(m);
    

如果运行:

java Freq if it is to be it is up to me to delegate

你会得到:

8 distinct words:
to=3, delegate=1, be=1, it=2, up=1, if=1, me=1, is=2

【讨论】:

【参考方案9】:

使用 ArrayList >

这里是代码示例:

ArrayList<Map<String, String>> products = new ArrayList<Map<String, String>>();
while (iterator.hasNext()) 
         Map<String, String> product = new HashMap<String, String>();
         Element currentProduct = iterator.next();
         product.put("id",currentProduct.get("id"));
         product.put("name" , currentProduct.get("name") );
         products.add(product );

System.out.println("products : " + products);

输出:

产品:[id=0001, name=prod1, id=0002, name=prod2]

【讨论】:

【参考方案10】:

Java 中的关联数组与 PHP 类似:

SlotMap hmap = new SlotHashMap();
String key = "k01";
String value = "123456";
// Add key value
hmap.put( key, value );

// check if key exists key value
if ( hmap.containsKey(key)) 
    //.....        


// loop over hmap
Set mapkeys =  hmap.keySet();
for ( Iterator iterator = mapkeys.iterator(); iterator.hasNext();) 
  String key = (String) iterator.next();
  String value = hmap.get(key);

更多信息,请参阅类 SoftHashMap:https://shiro.apache.org/static/1.2.2/apidocs/org/apache/shiro/util/SoftHashMap.html

【讨论】:

Map.containsKey() 方法遍历 Map 的所有键,Map.get() 方法也是如此,当找到键时它自然会返回一个值。因此,只需 Map.get() 执行这两种技术,只需一次(因此性能更高),而无需编写此新代码。此外 Map.get() 返回与匹配的第一个键关联的值,然后停止搜索,这更快,并且是此模式的熟悉行为。即使在搜索键匹配后,这篇文章中的代码也会继续遍历所有键,并返回最后一个匹配的键(不是第一个匹配的键)。【参考方案11】:

在 JDK 1.5 (http://tinyurl.com/3m2lxju) 中甚至有一个注释:“注意:这个类已经过时了。新的实现应该实现 Map 接口,而不是扩展这个类。” 问候,N.

【讨论】:

【参考方案12】:
Object[][] data = 
"mykey1", "myval1",
"mykey2", "myval2",
new Date(), new Integer(1),
;

是的,这需要迭代以按键搜索值,但如果您需要所有这些值,这将是最佳选择。

【讨论】:

【参考方案13】:

实际上 Java 确实支持关联数组,它们被称为字典!

【讨论】:

如果您引用 download.oracle.com/javase/1.4.2/docs/api/java/util/…,请注意该类 (a) 抽象且 (b) 已弃用。【参考方案14】:

想一想,我想把元组作为一种更通用的方法来处理这个问题。虽然元组不是 Java 原生的,但我使用 Javatuples 为我提供与其他语言相同的功能。如何处理提出的问题的一个例子是

Map<Pair<Integer, String>, String> arr = new HashMap<Pair<Integer, String>, String>();
Pair p1 = new Pair(0, "name");
arr.put(p1, "demo");

我喜欢这种方法,因为它可以通过 api 提供的类和方法扩展到三元组和其他更高阶的分组。

【讨论】:

【参考方案15】:

关于 PHP 注释“不,PHP 不喜欢它”。实际上,除非您设置一些非常严格的(对于 PHP)异常/错误级别,否则 PHP 会继续运行(甚至可能不会)。

默认情况下,访问不存在的变量/越界数组元素会“取消设置”您分配的值。不,那不是空的。据我了解,PHP 具有 Perl/C 血统。所以有:未设置和不存在的变量,已设置但为 NULL 的值,布尔 False 值,然后是标准语言所具有的所有其他内容。您必须单独测试这些,或者选择内置函数/语法的正确评估。

【讨论】:

以上是关于Java 关联数组的主要内容,如果未能解决你的问题,请参考以下文章

5.9 作为关联数组的对象

PHP 数组中的每个ID键关联一个值,可不可以关联两个值?

javascript关联数组顺序混乱,怎么办?

关联数组

php判断数组是关联数组还是数值数组

关联数组VS索引数组