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


214

Як я можу створювати та отримувати асоціативні масиви на Java, як я можу в PHP?

Наприклад:

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

Відповіді:


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 " - звідки ви отримуєте цю пораду? Ви майже ніколи не повинні вказувати коефіцієнт навантаження для 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, але чудове рішення. Дякую.
frostymarvelous

Навіщо використовувати List замість ArrayList? тут новачок Java.
Собіохолік

'Список' - це абстрактний клас, а 'ArrayList' - одна з реалізацій цього класу, є інші типи списків, похідних від того ж абстрактного класу. Тому через це ArrayList також є списком. Ви не можете створити екземпляр абстрактного класу, просто використовуйте його як тип тут, вам потрібно використовувати реалізацію для своїх примірників. Таким чином, список є типом, а ArrayList - примірником тут.
вета

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.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 = ...

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}

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


Метод 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}]


1

У JDK 1.5 (http://tinyurl.com/3m2lxju) є навіть примітка: "ПРИМІТКА. Цей клас застарів. Нові реалізації повинні реалізувати інтерфейс Map, а не розширювати цей клас." З повагою, Н.


1
Object[][] data = {
{"mykey1", "myval1"},
{"mykey2", "myval2"},
{new Date(), new Integer(1)},
};

Так, для цього потрібна ітерація пошуку значення за клавішею, але якщо вам потрібні всі, це буде найкращим вибором.



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 класів та методів.


-2

Щодо коментаря PHP "Ні, PHP не сподобається". Насправді, PHP буде продовжувати чинити, якщо ви не встановите дуже обмежуючі (для PHP) рівні винятків / помилок (і, можливо, навіть тоді).

Що станеться за замовчуванням, це те, що доступ до неіснуючої змінної / поза межами елемента масиву "скасовує" ваше значення, яке ви призначаєте. НІ, це НЕ нуль. PHP має лінію Perl / C, наскільки я розумію. Отож є: невстановлені та неіснуючі змінні, значення яких задано, але є NULL, булевими помилковими значеннями, то все інше, що є у стандартних мовах. Ви повинні перевірити їх окремо, АБО вибрати правильну оцінку, вбудовану у функцію / синтаксис.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.