Matriz asociativa de Java

214

¿Cómo puedo crear y buscar matrices asociativas en Java como puedo en PHP?

Por ejemplo:

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

Respuestas:

356

Java no admite matrices asociativas, sin embargo, esto podría lograrse fácilmente utilizando a Map. P.ej,

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

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

Aún más preciso para su ejemplo (ya que puede reemplazar String con cualquier objeto que satisfaga sus necesidades) sería declarar:

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

Consulte la documentación oficial para más información.

Johan Sjöberg
fuente
2
Esto arrojará NullPointerExceptionsi el mapa externo no contiene un mapa para la entrada 0. ¿No es PHP más permisivo con $ arr [0] ['nombre'] (no conozco este lenguaje en absoluto)?
Tomasz Nurkiewicz
99
A PHP no le gustaría si intentaras acceder a una clave que no existe, no :)
Svish
2
@edem, fue necesaria alguna implementación. Hoy sin embargo, yo preferiría ArrayListen casi todos los casos debido a inesperados (?) Las diferencias de rendimiento. Pero esa es otra discusión.
Johan Sjöberg
3
Nunca olvides inicializar el tamaño exacto de hash y establecer el factor de carga como 1: HashMap <String, String> (capacidad, 1). De lo contrario, puede implementar una gran sobrecarga y sus objetos necesitan mucha RAM. +1 para ArrayList, pero ¿por qué no editar la respuesta?
Marcus
1
@Marcus " Nunca olvides inicializar el tamaño exacto del hash y establecer el factor de carga en 1 ", ¿de dónde sacas ese consejo? Casi nunca debe especificar el factor de carga de a HashMap, y ciertamente no sin comparar intencionalmente el comportamiento y encontrar un mejor factor de carga para su caso de uso. La única razón para especificar un tamaño inicial es si sabe de antemano que el mapa será muy grande. HashMapno desperdicia (mucha) memoria si está vacía, pero si tiene la intención de crear un mapa grande, puede guardar varios tamaños de matriz especificando su tamaño por adelantado.
dimo414
47

Java no tiene matrices asociativas como PHP.

Existen varias soluciones para lo que está haciendo, como usar un Mapa, pero depende de cómo desee buscar la información. Puede escribir fácilmente una clase que contenga toda su información y almacenar instancias de ellos en un archivo ArrayList.

public class Foo{
    public String name, fname;

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

Y entonces...

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

Para que pueda acceder a ellos como ...

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

Puede lograr esto a través de Maps. Algo como

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

Pero cuando comience a usar Java, estoy seguro de que encontrará que si crea una clase / modelo que represente sus datos, serán sus mejores opciones. yo lo haría

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
fuente
Creo que me gusta más este método, gracias. Provenir de PHP, donde todo es tan simple, es algo incómodo con Java, pero es una gran solución. Gracias.
frostymarvelous
¿Por qué usar List en lugar de ArrayList? Un novato de Java aquí.
Sobiaholic
'Lista' es una clase abstracta y 'ArrayList' es una de las implementaciones de esa clase, hay otro tipo de listas derivadas de la misma clase abstracta. Por eso, una ArrayList es también una Lista. No puede crear una instancia de una clase abstracta, simplemente úsela como tipo aquí, debe usar la implementación para sus instancias. Entonces la Lista es el tipo, y ArrayList es la instancia aquí.
veta
12

No existe una matriz asociativa en Java. Su pariente más cercano es a Map, que está fuertemente tipado, pero tiene una sintaxis / API menos elegante.

Esto es lo más cercano que puede obtener según su ejemplo:

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
fuente
1
¿Para qué LazyMap.decoratey qué InstantiateFactory?
Svish
+1 Todas las otras respuestas parecen suponer que una de las "claves" es un número entero. ¿Qué pasa si la matriz asociada se basa en dos claves no enteras (una tupla que diríamos en python)? Creo que necesitaría usar este enfoque ya que la indexación se vuelve imposible.
demongolem
10

Mire la interfaz de Mapa y la clase concreta HashMap .

Para crear un mapa:

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

Para agregar un par clave-valor:

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

Para recuperar el valor asociado con una clave:

assoc.get("name")

Y claro, puede crear una serie de mapas, ya que parece ser lo que desea:

Map<String, String>[] assoc = ...
ChrisJ
fuente
6

Bueno, también estaba buscando una matriz asociativa y encontré la Lista de mapas como la mejor solución.

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

}


}
alquimista
fuente
5

Java no tiene matrices asociativas, lo más parecido que puede obtener es la interfaz de Mapa

Aquí hay una muestra de esa página.

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

Si se ejecuta con:

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

Obtendrás:

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

Matrices asociativas en Java como en 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);
}

Más información, consulte Clase SoftHashMap: https://shiro.apache.org/static/1.2.2/apidocs/org/apache/shiro/util/SoftHashMap.html

abahet
fuente
El método Map.containsKey () itera a través de todas las claves del Mapa, y también lo hace el método Map.get () que también naturalmente devuelve un valor cuando se encuentra la clave. Entonces, solo Map.get () realiza ambas técnicas, solo una vez (de manera más eficiente), sin escribir este nuevo código. También Map.get () devuelve el valor asociado con la primera clave coincidente, y luego deja de buscar, que es más rápido y el comportamiento familiar para este patrón. El código en esta publicación sigue iterando a través de todas las claves incluso después de que la clave de búsqueda coincida, y devuelve la última clave coincidente (no la primera clave coincidente).
Mateo
3

Utilice ArrayList <Map <String, String>>

Aquí un ejemplo de código:

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

Salida:

productos: [{id = 0001, nombre = prod1}, {id = 0002, nombre = prod2}]

abahet
fuente
1

En JDK 1.5 (http://tinyurl.com/3m2lxju) hay incluso una nota: "NOTA: Esta clase es obsoleta. Las nuevas implementaciones deberían implementar la interfaz de Mapa, en lugar de extender esta clase". Saludos, N.

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

Sí, esto requiere iteración para buscar valor por clave, pero si los necesita todos, esta será la mejor opción.

msangel
fuente
0

Pensando más en ello, me gustaría descartar las tuplas como una forma más general de tratar este problema. Si bien las tuplas no son nativas de Java, yo uso las tuplas de Java para proporcionarme la misma funcionalidad que existiría en otros idiomas. Un ejemplo de cómo lidiar con la pregunta formulada es

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

Me gusta este enfoque porque puede extenderse a triples y otras agrupaciones de orden superior con clases y métodos proporcionados por API.

demongolem
fuente
-2

En cuanto al comentario de PHP 'No, a PHP no le gustaría'. En realidad, PHP seguiría funcionando a menos que establezcas algunos niveles de excepción / error muy restrictivos (para PHP) (y tal vez ni siquiera entonces).

Lo que PASARÁ por defecto es que un acceso a un elemento de matriz variable / fuera de límites no existente 'desarma' su valor al que está asignando. NO, eso NO es nulo. PHP tiene un linaje Perl / C, por lo que entiendo. Entonces hay: variables no establecidas y no existentes, valores que ESTÁN establecidos pero son NULOS, valores falsos booleanos, luego todo lo demás que tienen los idiomas estándar. Debe probarlos por separado, O elegir la función / sintaxis incorporada de la evaluación CORRECTA.

Dennis
fuente