Java associative-array (Programare, Java, Hashmap, Matrice Asociativă)

dobs a intrebat.

Cum pot crea și prelua array-uri asociative în Java așa cum pot face în PHP?

De exemplu:

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

15 răspunsuri
Johan Sjöberg

Java nu suportă array-uri asociative, însă acest lucru ar putea fi realizat cu ușurință folosind un Map. De ex,

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

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

Chiar mai exact pentru exemplul dvs. (deoarece puteți înlocui String cu orice obiect care satisface nevoile dvs.) ar fi să declarați:

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

Pentru mai multe informații, consultați documentația oficială

Comentarii

  • Acest lucru va arunca NullPointerException dacă harta exterioară nu conține harta pentru intrare 0. Nu este PHP mai permisiv cu $arr[0][‘name’] (nu cunosc deloc acest limbaj)? –  > Por Tomasz Nurkiewicz.
  • Lui PHP nu i-ar plăcea dacă ai încerca să accesezi o cheie care nu există, nu 🙂 –  > Por Svish.
  • @edem, unele implementare a fost necesară. Astăzi totuși, I aș prefera ArrayList în aproape toate cazurile din cauza diferențelor de performanță (neașteptate?). Dar asta este o altă discuție. –  > Por Johan Sjöberg.
  • Nu uitați niciodată să inițializați dimensiunea exactă a hash-ului și să setați factorul de încărcare ca fiind 1: HashMap<String, String>(capacity, 1). În caz contrar, este posibil să implementați o supraîncărcare uriașă și obiectele dvs. să necesite prea multă memorie RAM. +1 pentru ArrayList, dar de ce nu se editează răspunsul? –  > Por Marcus.
  • @Marcus „Nu uitați niciodată să inițializați dimensiunea exactă a hash-ului și să setați factorul de încărcare ca fiind 1” – de unde ai acest sfat? Ar trebui aproape niciodată specificați niciodată factorul de încărcare al unui HashMapși, cu siguranță, nu fără a analiza în mod intenționat comportamentul și a găsi un factor de încărcare mai bun pentru cazul de utilizare. Singurul motiv pentru a specifica o dimensiune inițială este dacă știți dinainte că harta va fi foarte mare. HashMap nu risipește (multă) memorie dacă este goală, dar dacă intenționați să creați o hartă mare, puteți economisi mai multe mărimi de tablouri dacă îi specificați dimensiunea în avans. –  > Por dimo414.
Jeremy

Java nu are array-uri asociative, așa cum are PHP.

Există diverse soluții pentru ceea ce faceți dumneavoastră, cum ar fi utilizarea unei hărți, dar depinde de modul în care doriți să căutați informațiile. Poți scrie cu ușurință o clasă care să dețină toate informațiile și să stochezi instanțele acestora într-un fișier ArrayList.

public class Foo{
    public String name, fname;

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

Și apoi…

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

Astfel încât să le puteți accesa ca…

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

Comentarii

  • Nu înțeleg, cum accesezi lucrurile după o cheie aici, am crezut că acesta este scopul principal de a avea o matrice asociativă. –  > Por windmaomao.
  • @windmaomao Nu ai cum. De aceea, răspunsul acceptat este să folosești un Map. –  > Por Jeremy.
  • O matrice asociativă este dinamică și flexibilă. Se pot adăuga noi atribute în timpul execuției. O clasă Java are un set predefinit de variabile de instanță, stabilit la compilare. –  > Por durette.
Amir Raminfar

Puteți realiza acest lucru prin intermediul Maps. Ceva de genul

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

Dar, pe măsură ce începeți să utilizați Java, sunt sigur că veți descoperi că dacă creați o clasă/model care să reprezinte datele dvs. vor fi cele mai bune opțiuni. Eu aș face

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

Comentarii

  • Cred că îmi place mai mult această metodă, mulțumesc. Venind din php unde totul este atât de simplu este un fel de ciudat folosind java, dar o soluție excelentă. Mulțumesc. –  > Por frostymarvelous.
  • De ce să folosiți List în loc de ArrayList? un începător java aici. –  > Por Sobiaholic.
  • ‘List’ este o clasă abstractă, iar ‘ArrayList’ este una dintre implementările acestei clase, există și alte tipuri de liste derivate din aceeași clasă abstractă. Deci, din acest motiv, un ArrayList este, de asemenea, o listă. Nu puteți crea o instanță a unei clase abstracte, ci doar să o utilizați ca tip aici, trebuie să utilizați implementarea pentru instanțele dumneavoastră. Așadar, List este tipul, iar ArrayList este instanța aici. –  > Por veta.
ChrisJ

Uitați-vă la Map și la clasa concretă HashMap.

Pentru a crea un Map:

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

Pentru a adăuga o pereche cheie-valoare:

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

Pentru a prelua valoarea asociată cu o cheie:

assoc.get("name")

Și, desigur, puteți crea o matrice de hărți, deoarece se pare că este ceea ce doriți:

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

Tomasz Nurkiewicz

În Java nu există o matrice asociativă. Cea mai apropiată rudă a sa este un Map, care este puternic tipizat, însă are o sintaxă/API mai puțin elegantă.

Acesta este cel mai apropiat pe care îl puteți obține pe baza exemplului dvs:

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

Comentarii

  • Care este LazyMap.decorate și InstantiateFactory și la ce folosește chestia cu and? –  > Por Svish.
  • +1 Toate celelalte răspunsuri par să presupună că una dintre „chei” este un număr întreg. Ce se întâmplă dacă matricea asociată se bazează pe două chei care nu sunt numere întregi (un tuple am spune în python)? Cred că ar trebui să folosiți această abordare, deoarece indexarea devine imposibilă. –  > Por demongolem.
alchimist

Ei bine, și eu am fost în căutare de matrice asociativă și am găsit lista de hărți ca fiind cea mai bună soluție.

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

}


}

DVK

Echivalentul Java al hash-ului din Perl

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

OscarRyz

Java nu are array-uri asociative, cel mai apropiat lucru pe care îl puteți obține este interfața Map

Iată o mostră din pagina respectivă.

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

Dacă se execută cu:

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

Veți obține:

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

abahet

Matrici asociative în Java ca în 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);
}

Pentru mai multe informații, consultați Clasa SoftHashMap : https://shiro.apache.org/static/1.2.2/apidocs/org/apache/shiro/util/SoftHashMap.html

Comentarii

  • Metoda Map.containsKey() parcurge toate cheile hărții, la fel ca și metoda Map.get(), care, de asemenea, returnează în mod natural o valoare atunci când cheia este găsită. Așadar, doar Map.get() realizează ambele tehnici, o singură dată (deci mai performantă), fără a scrie acest cod nou. De asemenea, Map.get() returnează valoarea asociată cu prima cheie găsită și apoi se oprește din căutare, ceea ce este mai rapid și reprezintă comportamentul obișnuit pentru acest model. Codul din această postare continuă să parcurgă toate cheile, chiar și după ce cheia de căutare a fost găsită, și returnează ultima cheie găsită (nu prima cheie găsită). –  > Por Matthew.
abahet

Utilizați ArrayList < Map < String, String > >

Iată un exemplu de cod :

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

Ieșire :

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

shadrik

În JDK 1.5 (http://tinyurl.com/3m2lxju) există chiar și o notă: „NOTĂ: Această clasă este depășită. Noile implementări ar trebui să implementeze interfața Map, mai degrabă decât să extindă această clasă.” Cu respect, N.

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

Da, acest lucru necesită iterație pentru căutarea valorii după cheie, dar dacă aveți nevoie de toate, aceasta va fi cea mai bună alegere.

Matt Seidlitz

De fapt, Java acceptă array-uri asociative, acestea se numesc dicționare!

Comentarii

demongolem

Gândindu-mă mai mult la asta, aș vrea să arunc tuplele ca o modalitate mai generală de a rezolva această problemă. Deși tuplele nu sunt native în Java, eu folosesc Javatuples pentru a-mi oferi aceeași funcționalitate care ar exista în alte limbaje. Un exemplu de abordare a întrebării adresate este următorul

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

Îmi place această abordare deoarece poate fi extinsă la triple și la alte grupări ordonate mai mari cu ajutorul claselor și metodelor furnizate de api.

Dennis

În ceea ce privește comentariul PHP „Nu, PHP nu i-ar plăcea”. De fapt, PHP ar continua să funcționeze, cu excepția cazului în care setați niște niveluri de excepție/error foarte restrictive (pentru PHP), (și poate nici măcar atunci).

Ceea ce se va întâmpla în mod implicit este că un acces la o variabilă inexistentă/un element de matrice în afara limitelor „anulează” valoarea pe care o atribuiți. NU, aceasta NU este nulă. PHP are o descendență Perl/C, din câte am înțeles. Deci, există: variabile nefixate și neexistente, valori care SUNT fixate, dar sunt NULL, valori booleene false, apoi toate celelalte valori pe care le au limbajele standard. Trebuie să le testați separat pentru acestea, SAU să alegeți funcția/sintaxa de evaluare corectă încorporată.