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

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


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"

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

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

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

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

}


}


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}

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


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}]


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.


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.



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.


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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.