232

How can I create and fetch associative arrays in Java like I can in PHP?

For example:

$arr[0]['name'] = 'demo';
$arr[0]['fname'] = 'fdemo';
$arr[1]['name'] = 'test';
$arr[1]['fname'] = 'fname';
xarlymg89
  • 2,552
  • 2
  • 27
  • 41
dobs
  • 2,742
  • 2
  • 21
  • 19

15 Answers15

385

Java doesn't support associative arrays, however this could easily be achieved using a Map. E.g.,

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

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

Even more accurate to your example (since you can replace String with any object that meet your needs) would be to declare:

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

See the official documentation for more information

dsh
  • 12,037
  • 3
  • 33
  • 51
Johan Sjöberg
  • 47,929
  • 21
  • 130
  • 148
  • 2
    This will throw `NullPointerException` if outer map does not contain map for entry `0`. Isn't PHP more permissive with $arr[0]['name'] (I don't know this language at all)? – Tomasz Nurkiewicz Feb 25 '11 at 21:49
  • 9
    PHP wouldn't like it if you tried to access a key that doesn't exist, no :) – Svish Aug 26 '11 at 07:29
  • Why are you using LinkedList? It's not a problem, I'm just curious. – Adam Arold Aug 14 '12 at 12:33
  • 2
    @edem, *some* implementation was necessary. *Today* however, **I** would prefer `ArrayList` in almost all cases due to (unexpected?) performance differences. But that's another discussion. – Johan Sjöberg Aug 14 '12 at 13:10
  • 3
    Never forget to initialise the exact hash size and set the load factor as 1: HashMap(capacity, 1). Otherwise you may implement a huge overhead and your objects needs to much RAM. +1 for ArrayList, but why no edit of the answer? – Marcus Feb 05 '13 at 01:53
  • but, what if the value must have a value that is not a String ? – Francisco Corrales Morales Apr 22 '14 at 20:03
  • why do you say that the second option is *more accurate* ? – Francisco Corrales Morales Jun 03 '14 at 22:04
  • @FranciscoCorralesMorales, you can replace string with any object that meet your needs. It's not that it's more *accurate*, but the second example closer matches what OP is asking for. – Johan Sjöberg Jun 04 '14 at 12:41
  • 1
    @Marcus "*Never forget to initialise the exact hash size and set the load factor as 1*" - where do you get that advice? You should almost *never* specify the load-factor of a `HashMap`, and certainly not without intentionally benchmarking the behavior and finding a better load-factor for your use case. The only reason to specify an initial size is if you know in advance that the map will be very large. `HashMap` does not waste (much) memory if empty, but if you intend to create a large map you can save several array-resizes by specifying it's size up front. – dimo414 Jan 12 '16 at 16:57
48

Java doesn't have associative arrays like PHP does.

There are various solutions for what you are doing, such as using a Map, but it depends on how you want to look up the information. You can easily write a class that holds all your information and store instances of them in an ArrayList.

public class Foo{
    public String name, fname;

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

And then...

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

So you can access them like...

foos.get(0).name;
=> "demo"
Martin.
  • 10,494
  • 3
  • 42
  • 68
Jeremy
  • 22,188
  • 4
  • 68
  • 81
  • I don't understand, how do you access things by a key here, i thought this is the main point of having associative array. – windmaomao Jul 20 '20 at 15:18
  • @windmaomao You don't. That's why the accepted answer is to use a Map. – Jeremy Oct 05 '20 at 11:15
  • An associative array is dynamic and flexible. New attributes can be added at runtime. A Java class has a predefined set of instance variables, set a compile time. – durette Dec 10 '20 at 20:53
20

You can accomplish this via Maps. Something like

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

But as you start using Java I am sure you will find that if you create a class/model that represents your data will be your best options. I would do

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);
huff
  • 1,954
  • 2
  • 28
  • 49
Amir Raminfar
  • 33,777
  • 7
  • 93
  • 123
  • I think I like this method better thanks. Coming from php where everything is so simple is sort of awkward using java, but great solution. Thanks. – frostymarvelous Jan 25 '12 at 12:58
  • Why use List instead of ArrayList? a java newbie here. – Sobiaholic Mar 18 '15 at 13:12
  • 'List' is an abstract class and 'ArrayList' is one of the implementations of that class, there are other type of lists derived from the same abstract class. So because of this an ArrayList is also a List. You cannot create an instance of an abstract class, just use it as type here, you need to use the implementation for your instances. So the List is the type, and ArrayList is the instance here. – veta Aug 26 '15 at 16:20
13

Look at the Map interface, and at the concrete class HashMap.

To create a Map:

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

To add a key-value pair:

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

To retrieve the value associated with a key:

assoc.get("name")

And sure, you may create an array of Maps, as it seems to be what you want:

Map<String, String>[] assoc = ...
ChrisJ
  • 5,161
  • 25
  • 20
12

There is no such thing as associative array in Java. Its closest relative is a Map, which is strongly typed, however has less elegant syntax/API.

This is the closest you can get based on your example:

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
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • 1
    What's the `LazyMap.decorate` and `InstantiateFactory` and stuff for? – Svish Aug 26 '11 at 07:30
  • +1 All the other answers seem to assume that one of the "keys" is an integer. What if the associate array was based upon two non-integer keys (a tuple we would say in python)? I believe you would need to use this approach as indexing becomes impossible. – demongolem Aug 30 '12 at 13:30
6

Well i also was in search of Associative array and found the List of maps as the best solution.

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

}


}
alchemist
  • 1,081
  • 12
  • 17
5

Java equivalent of Perl's hash

HashMap<Integer, HashMap<String, String>> hash;
Community
  • 1
  • 1
DVK
  • 126,886
  • 32
  • 213
  • 327
5

Java doesn't have associative arrays, the closest thing you can get is the Map interface

Here's a sample from that page.

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

If run with:

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

You'll get:

8 distinct words:
{to=3, delegate=1, be=1, it=2, up=1, if=1, me=1, is=2}
OscarRyz
  • 196,001
  • 113
  • 385
  • 569
4

Use ArrayList < Map < String, String > >

Here a code sample :

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

Output :

products : [{id=0001, name=prod1}, {id=0002, name=prod2}]

abahet
  • 10,355
  • 4
  • 32
  • 23
3

Associative arrays in Java like in 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);
}

More info, see Class SoftHashMap : https://shiro.apache.org/static/1.2.2/apidocs/org/apache/shiro/util/SoftHashMap.html

abahet
  • 10,355
  • 4
  • 32
  • 23
  • The Map.containsKey() method iterates through all the Map's keys, and so does the Map.get() method which also naturally returns a value when the key is found. So just Map.get() performs both those techniques, only once (so more performant), without writing this new code. Also Map.get() returns the value associated with the first key matched, and then stops searching, which is faster and the familiar behavior for this pattern. The code in this post keeps iterating through all the keys even after the search key is matched, and returns the last matched key (not the first matched key). – Matthew Aug 08 '16 at 19:38
2
Object[][] data = {
{"mykey1", "myval1"},
{"mykey2", "myval2"},
{new Date(), new Integer(1)},
};

Yes, this require iteration for searchting value by key, but if you need all of them, this will be the best choice.

msangel
  • 9,895
  • 3
  • 50
  • 69
1

In JDK 1.5 (http://tinyurl.com/3m2lxju) there is even a note: "NOTE: This class is obsolete. New implementations should implement the Map interface, rather than extending this class." Regards, N.

shadrik
  • 349
  • 1
  • 4
  • 10
0

Thinking more about it, I would like to throw out tuples as a more general-purpose way of dealing with this problem. While tuples are not native to Java, I use Javatuples to provide me the same functionality which would exist in other languages. An example of how to deal with the question asked is

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

I like this approach because it can be extended to triples and other higher ordered groupings with api provided classes and methods.

demongolem
  • 9,474
  • 36
  • 90
  • 105
0

Actually Java does support associative arrays they are called dictionaries!

  • 10
    If you refer to http://download.oracle.com/javase/1.4.2/docs/api/java/util/Dictionary.html then note that this class is (a) abstract and (b) deprecated. – Felix Kling Jun 09 '11 at 13:43
-2

Regarding the PHP comment 'No, PHP wouldn't like it'. Actually, PHP would keep on chugging unless you set some very restrictive (for PHP) exception/error levels, (and maybe not even then).

What WILL happen by default is that an access to a non existing variable/out of bounds array element 'unsets' your value that you're assigning to. NO, that is NOT null. PHP has a Perl/C lineage, from what I understand. So there are: unset and non existing variables, values which ARE set but are NULL, Boolean False values, then everything else that standard langauges have. You have to test for those separately, OR choose the RIGHT evaluation built in function/syntax.

Dennis
  • 747
  • 7
  • 15