Tablica asocjacyjna Java

214

Jak mogę tworzyć i pobierać tablice asocjacyjne w Javie tak jak w PHP?

Na przykład:

$arr[0]['name'] = 'demo';
$arr[0]['fname'] = 'fdemo';
$arr[1]['name'] = 'test';
$arr[1]['fname'] = 'fname';
dobs
źródło

Odpowiedzi:

356

Java nie obsługuje tablic asocjacyjnych, jednak można to łatwo osiągnąć za pomocą Map. Na przykład,

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

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

Jeszcze dokładniejszym przykładem (ponieważ możesz zastąpić String dowolnym obiektem spełniającym twoje potrzeby) byłoby zadeklarowanie:

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

Więcej informacji znajduje się w oficjalnej dokumentacji

Johan Sjöberg
źródło
2
Wyrzuci to, NullPointerExceptionjeśli mapa zewnętrzna nie zawiera mapy do wjazdu 0. Czy PHP nie jest bardziej liberalne z $ arr [0] ['name'] (w ogóle nie znam tego języka)?
Tomasz Nurkiewicz,
9
PHP nie spodobałoby się, gdybyś spróbował uzyskać dostęp do klucza, który nie istnieje, nie :)
Svish
2
@edem, niektóre realizacja była konieczna. Dziś jednak, że wolałby ArrayListw prawie wszystkich przypadkach ze względu na nieoczekiwane (?) Różnice wydajności. Ale to kolejna dyskusja.
Johan Sjöberg,
3
Nigdy nie zapomnij zainicjować dokładnego rozmiaru skrótu i ​​ustawić współczynnik obciążenia na 1: HashMap <String, String> (pojemność, 1). W przeciwnym razie możesz zaimplementować ogromny narzut, a twoje obiekty potrzebują dużo pamięci RAM. +1 dla ArrayList, ale dlaczego nie ma edycji odpowiedzi?
Marcus
1
@Marcus „ Nigdy nie zapomnij zainicjować dokładnego rozmiaru skrótu i ​​ustawić współczynnik obciążenia na 1 ” - skąd ta rada? Prawie nigdy nie powinieneś określać współczynnika obciążenia HashMap, a na pewno nie bez celowej analizy porównawczej zachowania i znalezienia lepszego współczynnika obciążenia dla twojego przypadku użycia. Jedynym powodem do określenia początkowego rozmiaru jest to, że wiesz z góry, że mapa będzie bardzo duża. HashMapnie marnuje (dużo) pamięci, jeśli jest pusta, ale jeśli zamierzasz stworzyć dużą mapę, możesz zapisać kilka rozmiarów tablicy, określając jej rozmiar z góry.
dimo414
47

Java nie ma tablic asocjacyjnych jak PHP.

Istnieją różne rozwiązania tego, co robisz, na przykład przy użyciu mapy, ale zależy to od sposobu wyszukiwania informacji. Możesz łatwo napisać klasę, która przechowuje wszystkie informacje i przechowywać ich wystąpienia w pliku ArrayList.

public class Foo{
    public String name, fname;

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

I wtedy...

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

Możesz więc uzyskać do nich dostęp jak ...

foos.get(0).name;
=> "demo"
Jeremy
źródło
20

Możesz to zrobić za pomocą Map. Coś jak

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

Ale kiedy zaczniesz używać Java, jestem pewien, że przekonasz się, że jeśli stworzysz klasę / model, który reprezentuje twoje dane, będą to najlepsze opcje. chciałbym zrobić

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);
Amir Raminfar
źródło
Myślę, że podoba mi się ta metoda, dzięki. Pochodzenie z php, gdzie wszystko jest tak proste, jest dość niewygodne przy użyciu Java, ale świetne rozwiązanie. Dzięki.
frostymarvellous
Dlaczego warto korzystać z List zamiast ArrayList? początkujący java tutaj.
Sobiaholic
„List” to klasa abstrakcyjna, a „ArrayList” jest jedną z implementacji tej klasy, istnieją też inne typy list pochodzących z tej samej klasy abstrakcyjnej. Z tego powodu ArrayList jest również Listą. Nie możesz utworzyć instancji klasy abstrakcyjnej, po prostu użyj jej jako typu tutaj, musisz użyć implementacji dla swoich instancji. Zatem lista jest typem, a ArrayList jest tutaj instancją.
veta
12

W Javie nie ma czegoś takiego jak tablica asocjacyjna. Jego najbliższym krewnym jest Mapmocno wpisany typ, jednak ma on mniej elegancką składnię / interfejs API.

To jest najbliższe, jakie możesz uzyskać na podstawie twojego przykładu:

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
źródło
1
Co to jest LazyMap.decoratei InstantiateFactoryi rzeczy dla?
Svish,
+1 Wszystkie pozostałe odpowiedzi wydają się zakładać, że jeden z „kluczy” jest liczbą całkowitą. Co jeśli tablica asocjacyjna była oparta na dwóch kluczach niecałkowitych (krotkę powiedzielibyśmy w pythonie)? Uważam, że trzeba by zastosować to podejście, ponieważ indeksowanie staje się niemożliwe.
demongolem
10

Spójrz na interfejs Map i na konkretną klasę HashMap .

Aby utworzyć mapę:

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

Aby dodać parę klucz-wartość:

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

Aby pobrać wartość powiązaną z kluczem:

assoc.get("name")

I oczywiście możesz stworzyć tablicę map, ponieważ wydaje się, że jest to, czego chcesz:

Map<String, String>[] assoc = ...
ChrisJ
źródło
6

Cóż, również szukałem tablicy asocjacyjnej i znalazłem listę map jako najlepsze rozwiązanie.

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

}


}
alchemik
źródło
5

Java nie ma tablic asocjacyjnych, najbliższą rzeczą, jaką możesz uzyskać, jest interfejs Map

Oto próbka z tej strony.

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

Jeśli działa z:

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

Dostaniesz:

8 distinct words:
{to=3, delegate=1, be=1, it=2, up=1, if=1, me=1, is=2}
OscarRyz
źródło
3

Tablice asocjacyjne w Javie jak w 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);
}

Więcej informacji znajduje się w części SoftHashMap klasy: https://shiro.apache.org/static/1.2.2/apidocs/org/apache/shiro/util/SoftHashMap.html

abahet
źródło
Metoda Map.containsKey () dokonuje iteracji przez wszystkie klucze mapy, podobnie jak metoda Map.get (), która również naturalnie zwraca wartość po znalezieniu klucza. Tak więc tylko Map.get () wykonuje obie te techniki, tylko raz (tak wydajniej), bez pisania tego nowego kodu. Również Map.get () zwraca wartość powiązaną z pierwszym dopasowanym kluczem, a następnie zatrzymuje wyszukiwanie, co jest szybsze i znane zachowanie tego wzorca. Kod w tym poście nieustannie iteruje przez wszystkie klucze, nawet po dopasowaniu klucza wyszukiwania, i zwraca ostatni dopasowany klucz (nie pierwszy dopasowany klucz).
Matthew
3

Użyj ArrayList <Mapa <Ciąg, Ciąg>>

Oto przykładowy kod:

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

Wynik :

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

abahet
źródło
1

W JDK 1.5 (http://tinyurl.com/3m2lxju) jest nawet notatka: „UWAGA: Ta klasa jest przestarzała. Nowe implementacje powinny implementować interfejs Map zamiast rozszerzać tę klasę”. Pozdrawiam, N.

Shadrik
źródło
1
Object[][] data = {
{"mykey1", "myval1"},
{"mykey2", "myval2"},
{new Date(), new Integer(1)},
};

Tak, wymaga to iteracji do wyszukiwania wartości według klucza, ale jeśli potrzebujesz ich wszystkich, będzie to najlepszy wybór.

msangel
źródło
0

Zastanawiając się nad tym, chciałbym wyrzucić krotki jako bardziej ogólny sposób radzenia sobie z tym problemem. Krotki nie są rodzime dla Javy, ale używam Javatuples, aby zapewnić mi tę samą funkcjonalność, która istniałaby w innych językach. Przykładem postępowania z zadanym pytaniem jest

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

Podoba mi się to podejście, ponieważ można je rozszerzyć na potrójne i inne wyżej uporządkowane grupy za pomocą klas i metod udostępnianych przez API.

demongolem
źródło
-2

Odnośnie komentarza PHP „Nie, PHP nie spodoba się”. W rzeczywistości PHP nadal się ładował, chyba że ustawisz bardzo restrykcyjne (dla PHP) poziomy wyjątków / błędów (a może nawet nie wtedy).

To, co stanie się domyślnie, to to, że dostęp do nieistniejącej zmiennej / elementu poza granicami tablicy „rozbija” twoją wartość, do której przypisujesz. NIE, to NIE jest zero. Z tego, co rozumiem, PHP ma rodowód Perl / C. Są więc: zmienne nieustalone i nieistniejące, wartości, które SĄ ustawione, ale NULL, wartości logiczne Fałsz, a następnie wszystko inne, co mają standardowe języki. Musisz przetestować je osobno, LUB wybrać PRAWĄ ocenę wbudowaną funkcję / składnię.

Dennis
źródło