Matriz associativa Java

214

Como posso criar e buscar matrizes associativas em Java, como posso no PHP?

Por exemplo:

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

Respostas:

356

Java não suporta matrizes associativas, no entanto, isso pode ser facilmente alcançado usando a Map. Por exemplo,

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

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

Ainda mais preciso para o seu exemplo (já que você pode substituir String por qualquer objeto que atenda às suas necessidades) seria declarar:

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

Veja a documentação oficial para mais informações

Johan Sjöberg
fonte
2
Isso será lançado NullPointerExceptionse o mapa externo não contiver mapa para entrada 0. O PHP não é mais permissivo com $ arr [0] ['name'] (eu não conheço essa linguagem)?
Tomasz Nurkiewicz
9
PHP não gostaria que se você tentou acessar uma chave que não existe, não :)
Svish
2
@edem, alguma implementação foi necessária. Hoje , no entanto, eu preferiria ArrayListem quase todos os casos devido a diferenças de desempenho (inesperadas?). Mas isso é outra discussão.
Johan Sjöberg
3
Nunca se esqueça de inicializar o tamanho exato do hash e definir o fator de carga como 1: HashMap <String, String> (capacidade, 1). Caso contrário, você poderá implementar uma sobrecarga enorme e seus objetos precisarão de muita RAM. +1 para ArrayList, mas por que não editar a resposta?
Marcus
1
@ Marcus " Nunca se esqueça de inicializar o tamanho exato do hash e definir o fator de carga como 1 " - onde você consegue esse conselho? Você quase nunca deve especificar o fator de carga de a HashMap, e certamente não sem fazer um benchmark intencional do comportamento e encontrar um melhor fator de carga para o seu caso de uso. O único motivo para especificar um tamanho inicial é se você souber com antecedência que o mapa será muito grande. HashMapnão desperdiça (muita) memória se estiver vazia, mas se você pretende criar um mapa grande, pode salvar vários redimensionamentos de matriz especificando seu tamanho antecipadamente.
dimo414
47

Java não possui matrizes associativas, como o PHP.

Existem várias soluções para o que você está fazendo, como usar um mapa, mas isso depende de como você deseja procurar as informações. Você pode escrever facilmente uma classe que contém todas as suas informações e armazenar instâncias delas em um arquivo ArrayList.

public class Foo{
    public String name, fname;

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

E depois...

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

Então você pode acessá-los como ...

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

Você pode fazer isso através do Maps. Algo como

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

Mas, ao começar a usar Java, tenho certeza de que descobrirá que, se você criar uma classe / modelo que represente seus dados, serão suas melhores opções. eu faria

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
fonte
Acho que gosto mais desse método, obrigado. Vir do php, onde tudo é tão simples, é meio estranho usando java, mas é uma ótima solução. Obrigado.
Frostymarvelous
Por que usar Lista em vez de ArrayList? um novato em java aqui.
Sobiaholic 18/03/2015
'List' é uma classe abstrata e 'ArrayList' é uma das implementações dessa classe; existem outros tipos de listas derivadas da mesma classe abstrata. Portanto, por causa disso, um ArrayList também é uma lista. Você não pode criar uma instância de uma classe abstrata, apenas use-a como tipo aqui, você precisa usar a implementação para suas instâncias. Portanto, a lista é o tipo e ArrayList é a instância aqui.
veta
12

Não existe array associativo em Java. Seu parente mais próximo é um Map, que é fortemente tipado, mas possui sintaxe / API menos elegante.

Este é o mais próximo que você pode chegar com base no seu exemplo:

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
fonte
1
Para que serve o LazyMap.decoratee InstantiateFactory?
Svish
+1 Todas as outras respostas parecem assumir que uma das "chaves" é um número inteiro. E se a matriz associada fosse baseada em duas chaves não inteiras (uma tupla que diríamos em python)? Acredito que você precisaria usar essa abordagem, pois a indexação se torna impossível.
Demongolem 30/08
10

Veja a interface do mapa e a classe concreta HashMap .

Para criar um mapa:

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

Para adicionar um par de valores-chave:

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

Para recuperar o valor associado a uma chave:

assoc.get("name")

E, com certeza, você pode criar uma matriz de mapas, pois parece ser o que você deseja:

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

Bem, eu também estava em busca de matriz associativa e encontrei a lista de mapas como a melhor solução.

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
fonte
5

Java não possui matrizes associativas, o mais próximo que você pode obter é a interface do mapa

Aqui está um exemplo dessa 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);
    }
}

Se executado com:

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

Você terá:

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

Matrizes associativas em Java, como no 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);
}

Mais informações, consulte Classe SoftHashMap: https://shiro.apache.org/static/1.2.2/apidocs/org/apache/shiro/util/SoftHashMap.html

abahet
fonte
O método Map.containsKey () repete todas as chaves do mapa, e o método Map.get (), que também naturalmente retorna um valor quando a chave é encontrada. Portanto, apenas o Map.get () executa essas duas técnicas, apenas uma vez (com maior desempenho), sem escrever esse novo código. Map.get () também retorna o valor associado à primeira chave correspondente e, em seguida, para de procurar, o que é mais rápido e o comportamento familiar desse padrão. O código nesta postagem mantém a iteração em todas as chaves, mesmo após a correspondência da chave de pesquisa, e retorna a última chave correspondente (não a primeira chave correspondente).
Matthew
3

Use ArrayList <Map <String, String>>

Aqui está um exemplo 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);

Resultado :

produtos: [{id = 0001, nome = prod1}, {id = 0002, nome = prod2}]

abahet
fonte
1

No JDK 1.5 (http://tinyurl.com/3m2lxju) há até uma nota: "NOTA: Esta classe é obsoleta. Novas implementações devem implementar a interface do Mapa, em vez de estender essa classe". Atenciosamente, N.

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

Sim, isso requer iteração para pesquisar valor por chave, mas se você precisar de todos eles, esta será a melhor opção.

msangel
fonte
0

Pensando mais sobre isso, gostaria de lançar as tuplas como uma maneira mais geral de lidar com esse problema. Embora as tuplas não sejam nativas do Java, eu uso o Javatuples para me fornecer a mesma funcionalidade que existiria em outros idiomas. Um exemplo de como lidar com a pergunta feita é

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

Eu gosto dessa abordagem porque ela pode ser estendida a triplos e outros agrupamentos de ordem superior com classes e métodos fornecidos pela API.

demongolem
fonte
-2

Em relação ao comentário do PHP 'Não, o PHP não gostaria'. Na verdade, o PHP continuaria fazendo chug, a menos que você defina alguns níveis de exceção / erro muito restritivos (para PHP), (e talvez nem isso ainda).

O que acontecerá por padrão é que o acesso a um elemento de matriz variável / fora dos limites não existente 'desativa' o seu valor ao qual você está atribuindo. NÃO, isso NÃO é nulo. PHP tem uma linhagem Perl / C, pelo que entendi. Portanto, existem: variáveis ​​não definidas e não existentes, valores que SÃO configurados, mas são NULL, valores Boolean False, e tudo o mais que os idiomas padrão possuem. Você deve testá-los separadamente, OU escolher a função / sintaxe da avaliação DIREITA.

Dennis
fonte