Java关联数组

232

我如何在Java中创建和获取像PHP中的关联数组?

例如:

$arr[0]['name'] = 'demo';
$arr[0]['fname'] = 'fdemo';
$arr[1]['name'] = 'test';
$arr[1]['fname'] = 'fname';
15个回答

385

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

查看官方文档以获取更多信息


2
如果外部映射不包含条目“0”的映射,则会抛出“NullPointerException”。PHP对于$ arr [0] ['name']更加宽容(我根本不了解这种语言)是吗? - Tomasz Nurkiewicz
9
如果您尝试访问一个不存在的键,PHP 会不高兴的,呵呵 :) - Svish
2
@edem,一些实现是必要的。然而,今天,由于(意外的?)性能差异,我几乎在所有情况下都更喜欢使用ArrayList。但这是另一个讨论话题。 - Johan Sjöberg
3
永远不要忘记初始化精确哈希表大小并将负载因子设置为1:HashMap<String,String>(capacity,1)。否则你可能会实现巨大的开销,你的对象需要太多的RAM。赞成ArrayList,但为什么不编辑答案? - Marcus
2
@Marcus“永远不要忘记初始化确切的哈希大小并将负载因子设置为1”-你从哪里得到这个建议?你几乎永远不应该指定HashMap的负载因子,而且肯定不应该在没有有意识地基准测试行为并找到更好的负载因子的情况下指定它。指定初始大小的唯一原因是如果您事先知道映射将非常大。如果为空,HashMap不会浪费(很多)内存,但是如果您打算创建一个大型映射,则可以通过预先指定其大小来保存几个数组调整大小操作。 - dimo414
显示剩余4条评论

48

Java没有像PHP一样的关联数组。

有许多解决方案可以完成你要做的事情,例如使用Map,但这取决于你如何查找信息。你可以轻松编写一个类来保存所有信息,并将它们的实例存储在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
@windmaomao 你不需要这样做。这就是为什么被接受的答案是使用Map的原因。 - Jeremy
关联数组是动态和灵活的。可以在运行时添加新属性。Java类具有预定义的一组实例变量,在编译时设置。 - durette

20
您可以通过 Maps 实现此功能。类似于:
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,一切都变得有些尴尬,但这是一个很好的解决方案。谢谢。 - frostymarvelous
为什么要使用List而不是ArrayList?我是一个Java新手。 - Sobiaholic
“List”是一个抽象类,“ArrayList”是该类的实现之一,还有其他类型的列表都是从同一抽象类派生而来。因此,由于这个原因,ArrayList也是一个List。您不能创建抽象类的实例,只能在此处使用它作为类型,您需要为您的实例使用实现。所以List是类型,ArrayList是实例。 - veta

13

查看 Map 接口和具体类 HashMap

创建 Map:

Map<String, String> assoc = new HashMap<String, String>();
添加键值对的方法是:
assoc.put("name", "demo");

获取与键相关联的值:

assoc.get("name")

当然,你可以创建一个Map数组,因为这似乎是你想要的:

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

12

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

1
LazyMap.decorateInstantiateFactory是用来做什么的? - Svish
+1 所有其他答案似乎都假设“键”之一是整数。如果关联数组基于两个非整数键(在Python中我们会称之为元组),那该怎么办?我认为你需要使用这种方法,因为索引变得不可能。 - demongolem

6

我也在寻找关联数组,并认为 Map 列表是最好的解决方案。

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

}


}

5

5

Java中没有关联数组,最接近的东西是Map接口

以下是来自该页面的示例。

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}

4

使用 ArrayList < Map < String, String > >。

这是一个代码示例:

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,名称=prod1},{id=0002,名称=prod2}]


3

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

更多信息,请参见Class 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() 返回与第一个匹配的键关联的值,然后停止搜索,这是更快和更熟悉的模式行为。本帖中的代码即使在匹配搜索键后仍继续迭代所有键,并返回最后匹配的键(而不是第一个匹配的键)。 - Matthew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接