Java ассоциативный массив

214

Как я могу создавать и извлекать ассоциативные массивы в Java, как я могу в PHP?

Например:

$arr[0]['name'] = 'demo';
$arr[0]['fname'] = 'fdemo';
$arr[1]['name'] = 'test';
$arr[1]['fname'] = 'fname';
Dobs
источник

Ответы:

356

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
Это бросит, NullPointerExceptionесли внешняя карта не содержит карту для входа 0. Разве PHP не разрешает использовать $ arr [0] ['name'] (я вообще не знаю этот язык)?
Томаш Нуркевич
9
PHP не понравится, если вы попытаетесь получить доступ к ключу, который не существует, нет :)
Svish
2
@edem, некоторая реализация была необходима. Однако сегодня я бы предпочел ArrayListпочти во всех случаях из-за (неожиданных?) Различий в производительности. Но это другое обсуждение.
Йохан Шёберг
3
Никогда не забывайте инициализировать точный размер хэша и установить коэффициент загрузки равным 1: HashMap <String, String> (емкость, 1). В противном случае вы можете реализовать огромные накладные расходы, и вашим объектам потребуется много оперативной памяти. +1 для ArrayList, но почему нет редактирования ответа?
Маркус
1
@Marcus " Никогда не забывайте инициализировать точный размер хэша и установить коэффициент загрузки равным 1 " - где вы получите этот совет? Вы почти никогда не должны указывать коэффициент загрузки a HashMap, и, конечно, не без преднамеренного сравнения поведения и поиска лучшего коэффициента загрузки для вашего варианта использования. Единственная причина указать начальный размер - если вы заранее знаете, что карта будет очень большой. HashMapне тратит (много) памяти, если она пуста, но если вы намереваетесь создать большую карту, вы можете сохранить несколько размеров массива, указав его размер заранее.
dimo414
47

В 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"
Джереми
источник
20

Вы можете сделать это через Карты. Что-то вроде

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? Ява новичок здесь.
Собиоголик,
«List» - это абстрактный класс, а «ArrayList» - одна из реализаций этого класса, существуют списки другого типа, производные от того же абстрактного класса. Поэтому из-за этого ArrayList также является списком. Вы не можете создать экземпляр абстрактного класса, просто используйте его здесь как тип, вам нужно использовать реализацию для ваших экземпляров. Таким образом, List является типом, а ArrayList является экземпляром здесь.
Вета
12

В Java нет такого понятия, как ассоциативный массив. Его ближайший родственник - a 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.decorateи InstantiateFactoryдля чего?
Свиш
+1 Все остальные ответы, похоже, предполагают, что один из «ключей» является целым числом. Что если ассоциированный массив основан на двух нецелочисленных ключах (кортеж, который мы бы сказали в python)? Я считаю, что вам нужно использовать этот подход, так как индексация становится невозможной.
демонголем
10

Посмотрите на интерфейс Map и конкретный класс HashMap .

Чтобы создать карту:

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

Чтобы добавить пару ключ-значение:

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

Чтобы получить значение, связанное с ключом:

assoc.get("name")

И, конечно же, вы можете создать массив карт, как это кажется, что вы хотите:

Map<String, String>[] assoc = ...
ChrisJ
источник
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);

}


}
алхимик
источник
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}
OscarRyz
источник
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);
}

Дополнительную информацию см. В разделе Класс SoftHashMap: https://shiro.apache.org/static/1.2.2/apidocs/org/apache/shiro/util/SoftHashMap.html.

abahet
источник
Метод Map.containsKey () перебирает все ключи Map, как и метод Map.get (), который также естественным образом возвращает значение при обнаружении ключа. Так что просто Map.get () выполняет оба эти метода, только один раз (так более производительно), без написания этого нового кода. Также Map.get () возвращает значение, связанное с первым подобранным ключом, и затем прекращает поиск, что является более быстрым и привычным поведением для этого шаблона. Код в этом посте продолжает перебирать все ключи даже после сопоставления ключа поиска и возвращает последний совпавший ключ (не первый совпавший ключ).
Мэтью
3

Использовать 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, name = prod1}, {id = 0002, name = prod2}]

abahet
источник
1

В JDK 1.5 (http://tinyurl.com/3m2lxju) есть даже примечание: «ПРИМЕЧАНИЕ. Этот класс устарел. Новые реализации должны реализовывать интерфейс Map, а не расширять этот класс». С уважением, Н.

shadrik
источник
1
Object[][] data = {
{"mykey1", "myval1"},
{"mykey2", "myval2"},
{new Date(), new Integer(1)},
};

Да, это требует итерации для поиска значения по ключу, но если вам нужны все из них, это будет лучшим выбором.

msangel
источник
0

На самом деле Java поддерживает ассоциативные массивы, они называются словарями!

Мэтт Сейдлиц
источник
10
Если вы ссылаетесь на download.oracle.com/javase/1.4.2/docs/api/java/util/…, обратите внимание, что этот класс является (а) абстрактным и (б) не рекомендуемым.
Феликс Клинг
0

Размышляя больше об этом, я хотел бы выбросить кортежи как более общий способ решения этой проблемы. Хотя кортежи не являются родными для 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 и классов и методов.

demongolem
источник
-2

Что касается комментария PHP «Нет, PHP не понравится». На самом деле, PHP будет продолжать пускаться в пух, если вы не установите очень ограничительные (для PHP) уровни исключений / ошибок (и, возможно, даже тогда).

По умолчанию будет происходить то, что доступ к несуществующей переменной / элементу массива out of bounds 'отменяет' ваше значение, которое вы присваиваете. НЕТ, это НЕ НУЛЬ. PHP имеет родословную Perl / C, насколько я понимаю. Итак, есть: неустановленные и несуществующие переменные, значения, которые установлены, но имеют значение NULL, логические значения False, затем все остальное, что есть в стандартных языках. Вы должны проверить их отдельно, ИЛИ выбрать ПРАВУЮ оценку, встроенную в функцию / синтаксис.

Деннис
источник