Como fazer ArrayList bidimensional?
Olá,
Estou fazendo um jogo do tipo "warcraft"/"age of empires" e tenho que gerenciar a posição das unidades(objeto Unidade) nas cordenadas X e Y.
Pensei em usar um ArrayList bidimensional, onde as cordenadas seriam os indices, mas eu não sei como fazer isso, alguem poderia me mostrar como iniciar, ler e regravar um array assim?
LEMBRANDO que eu quero armazenar no ArrayList SOMENTE as unidades ativas...cordenadas vazias serão ignoradas já que a area é muito grande(por isso não posso usar arrays normal de tamanho fixo).
Obrigado.
Daniel Gimenes
Curtidas 0
Melhor post
Ricardo Staroski
16/07/2013
Parando pra pensar, acredito que seja mais otimizado você utilizar dois Maps ao invés de duas Lists.
Criei uma classe que implementa a funcionalidade de uma matriz bidimensional, vejá só:
Código de teste:
Agora a implementação da matriz dinamica:
public class Teste {
public static void main(String[] args) {
// criando uma matriz dinâmica de String, poderia ser de qualquer outra coisa
MatrizDinamica<String> matriz = new MatrizDinamica<String>();
int linhas = 10;
int colunas = 5;
for (int i = 0; i < linhas; i++) {
for (int j = 0; j < colunas; j++) {
String elemento = "linha: " + i + ", coluna: " + j;
matriz.set(i, j, elemento); // inserindo o elemento
}
}
for (int i = 0; i < linhas; i++) {
for (int j = 0; j < colunas; j++) {
String elemento = matriz.get(i, j); // obtendo o elementos
System.out.println(elemento);
}
}
}
}
import java.util.*;
public class MatrizDinamica<T> {
private final Map<Integer, Map<Integer, T>> elementos = new HashMap<Integer, Map<Integer, T>>();
public void set(int linha, int coluna, T elemento) {
Map<Integer, T> colunas = getColunas(linha);
Integer chave = Integer.valueOf(coluna);
if (elemento != null) {
colunas.put(chave, elemento);
} else {
colunas.remove(chave);
}
}
public T get(int linha, int coluna) {
Map<Integer, T> colunas = getColunas(linha);
Integer chave = Integer.valueOf(coluna);
T elemento = colunas.get(chave);
return elemento;
}
private Map<Integer, T> getColunas(int linha) {
int chave = Integer.valueOf(linha);
Map<Integer, T> colunas = elementos.get(chave);
if (colunas == null) {
colunas = new HashMap<Integer, T>();
elementos.put(chave, colunas);
}
return colunas;
}
}
GOSTEI 1
Mais Respostas
Ricardo Staroski
15/07/2013
Assim como um array bi-dimensional nada mais é do que um array de arrays, uma lista bidimensional pode ser representada por uma lista de listas:
List<List<TipoDeDado>> listaDeListas = new ArrayList<List<TipoDeDado>>();
GOSTEI 0
Thiago Palmeira
15/07/2013
Veja esse artigo, talvez possa te ajudar...
https://www.devmedia.com.br/trabalhando-com-arrays-em-java/25530
GOSTEI 0
Daniel Gimenes
15/07/2013
[quote="staroski"]Parando pra pensar, acredito que seja mais otimizado você utilizar dois Maps ao invés de duas Lists.
Cara nossa, valew, ajudou muito...só uma duvida, pq o hashmap é melhor que o arraylist neste caso especifico?
Ah...e desculpe a ignorancia em hashmap, nunca tinha usado...como faço para destruir um elemento? E para mover um elemento para outro indice?
Valew
GOSTEI 0
Ricardo Staroski
15/07/2013
A diferença entre um List e um Map é que um List guarda seus elementos em índices e um Map utiliza chaves.
No seu caso, as chaves vão ser o número da linha num Map e o número da coluna em outro Map.
Para remover um elemento você utiliza o método remove, se você olhar a implementação que fiz, isso acontece no método set da classe MatrizDinamica, se tu setar um elemento como null, o elemento que estava naquela coordenada, vai ser removido.
Se você quisesse usar List teria que ter uma estrutura de dados propria pra poder mapear a linha e coluna do objeto inserido, daria um trabalhão, imagina que sua lista tenha 10 elementos e você quer inserir um na posição 20, terias que inserir 9 elementos dummy para poder aí inserir no índice 20 o objeto que você quer.
Com o Map não acontece isso, o Map não é uma lista encadeada, ele é um par chave-valor.
GOSTEI 0
Thiago Palmeira
15/07/2013
Bacana muito bem bolado o código...
GOSTEI 0
Leonardo Oliveira
15/07/2013
Monstruoso esse codigo!!!
GOSTEI 0
Ricardo Staroski
15/07/2013
[quote="leonardooliveira"]Monstruoso esse codigo!!!
Monstruoso porque?
Não vejo monstruosidade em um método set para setar o elemento numa posição e um método get para obter o elemento de determinada posição...
GOSTEI 0
Carlos Rocha
15/07/2013
Estou com uma dúvida que talvez possam me ajudar.
Imagine a cena de um ArrayList de ArrayList de inteiros da forma abaixo
1 -> [3,1,8,9]
ArrayList 2 -> [10,2,4,5]
3 -> [9,3,4,5,5,9,0]
Como faço para remover apenas um índice do arrayList[2]. No caso a posição 0 que representa o número 10.
Tentei da duas formas abaixo:
listaRepetida2[conta[i]].remove(conta[i+1]);
listaRepetida2[conta[i]].remove(conta[i+1]);
e....
listaRepetida2.get(conta.get(i)).remove(conta.get(i+1));
listaRepetida2.get(conta.get(i)).remove(conta.get(i+1));
Mas nenhuma delas funcionou.
No caso elas estão em um loop de um ArrayList de inteiros que retorna apenas 1 posição com [1,0,1]
for (int i = 0; i < conta.size(); i++)
{
listaRepetida2[conta[i]].remove(conta[i+1]);
listaRepetida2[conta[i]].remove(conta[i+1]);
/*
listaRepetida2.get(conta.get(i)).remove(conta.get(i+1));
listaRepetida2.get(conta.get(i)).remove(conta.get(i+1));
*/
i+=2;
}
Pode me ajudar?
Desde já obrigado!
Carlos Rocha
GOSTEI 0
Ricardo Staroski
15/07/2013
Posta o código completo de seu fonte e explique com clareza o que você quer fazer.
Se você quer remover elementos de uma lista que está dentro de outra, o caminho é esse:
List listaInterna = listaExterna.get( posicaoDaListaQueQueroAcessar ); listaInterna.remove( posicaoDoElementoQueQueroRemoverDaListaInterna );
GOSTEI 0
Carlos Rocha
15/07/2013
Ok. Me perdoe por ter duplicado o post. Isso não mais se repetirá.
É o seguinte:
Tenho a classe abaixo que tem um atributo que é um Array<Array<Integer>>.
Nela, tenho um método que trata de ver se nesses arrays existe alguma sequencia de 2 pontos que se repetem e excluilos.
O Array Conta traz 2 indices.
1 -> O index do Array Pai
2 -> O index do Array Filho que será removido
A primeira volta do ArrayList conta me traz:
[1,0,1]
Que quer dizer, retirar do indice 1 do array pai, os indices 0 e 1 do seu filho
import java.util.ArrayList;
public class RemoveRepetidas
{
ArrayList<ArrayList<Integer>> listaRepetida = new ArrayList<ArrayList<Integer>>();
RemoveRepetidas (ArrayList<ArrayList<Integer>> _listaRepetida)
{
this.listaRepetida = _listaRepetida;
}
String removeRepetida()
{
System.out.println(this.listaRepetida);
ArrayList<Integer> conta = new ArrayList<Integer>();
ArrayList<ArrayList<Integer>> listaRepetida2 = listaRepetida;
for (int i = 0; i < listaRepetida2.size(); i++)
{
for (int j = i+1; j < listaRepetida2.size(); j++)
{
for (int k = 0; k < listaRepetida2.get(i).size(); k++)
{
for (int l = 0; l < listaRepetida2.get(j).size(); l++)
{
if (
( listaRepetida2.get(i).get(k) == listaRepetida2.get(j).get(l) && listaRepetida2.get(i).get(k+1) == listaRepetida2.get(j).get(l+1) ) ||
( listaRepetida2.get(i).get(k+1) == listaRepetida2.get(j).get(l) && listaRepetida2.get(i).get(k) == listaRepetida2.get(j).get(l+1) )
)
{
conta.add(j);
conta.add(l);
}
l++;
}
k++;
}
}
}
for (int i = 0; i < conta.size(); i++)
{
// NÃO ESTA REMOVENDO
listaRepetida2.get(conta.get(i)).remove(conta.get(i+1));
listaRepetida2.get(conta.get(i)).remove(conta.get(i+1));
i+=2;
}
String texto = "{";
texto += "}";
System.out.println(listaRepetida2);
return texto;
}
}
GOSTEI 0
Carlos Rocha
15/07/2013
Veja o que eu percebi:
Se eu fizer
Funciona.
Mas se fizer
Não funciona.
Porque será?
for (int i = 0; i < conta.size(); i++)
{
System.out.println(conta.get(i+1)); // isso retorna 0
System.out.println(conta.get(i+2)); // isso retorna 1
listaRepetida2.get(conta.get(i)).remove(conta.get(i+1));
listaRepetida2.get(conta.get(i)).remove(conta.get(i+2));
i+=2;
}
listaRepetida2.get(conta.get(i)).remove(0); listaRepetida2.get(conta.get(i)).remove(1);
listaRepetida2.get(conta.get(i)).remove(conta.get(i+1)); listaRepetida2.get(conta.get(i)).remove(conta.get(i+2));
GOSTEI 0
Carlos Rocha
15/07/2013
Consegui.
Agora estou tendo o seguinte retorno, é uma String:
Preciso transformar em:
Tentei:
e não funcionou.
C:\java\AD2\java>java Principal
{1,3,3,2,,1,4,,}
C:\java\AD2\java>
C:\java\AD2\java>java Principal
{1,3,3,2,1,4}
C:\java\AD2\java>
texto.replaceAll(",,",",");
System.out.println(texto);
GOSTEI 0
Ricardo Staroski
15/07/2013
Se você olhar a documentação da interface List, vai perceber que existem dois métodos [b]remove[/b]:
- um que espera como parâmetro um [b]tipo primitivo int[/b], correspondente à posição que você quer remover
- outro que espera o [b]objeto[/b] a ser removido da lista, independente de sua posição
O Java Collections Framework não suporta tipos primitivos, assim, o método [b]get(posicao)[/b] da interface List sempre retorna um [b]objeto[/b].
O código que você escreveu equivale a isso aqui:
Pois bem, evite escrever códigos como esse:
Com essas chamadas de métodos em cascata, você acaba se perdendo com o tipo de retorno e passagem de parâmetros.
Reescreva o seu código que vai funcionar.
Dica: Não chame o mesmo método mais de uma vez, guarde o resultado em uma variável local.
// posicao1 é do tipo objeto Integer e não tipo primitivo int Integer posicao1 = conta.get(i); // posicao2 também é do tipo objeto Integer e não tipo primitivo int Integer posicao2 = conta.get(i + 1); // o método get espera receber um tipo primitivo int e você está passando um objeto Integer, // neste caso, a JVM faz o auto unboxing de Integer para int // mas o método remove é sobrecarregado, // existe um remove que espera um tipo primitivo int // e existe o remove que espera um objeto // você está invocando o remove que espera o objeto a ser removido e não a posição a ser removida listaRepetida2.get(posicao1).remove(posicao2); listaRepetida2.get(posicao1).remove(posicao2);
listaRepetida2.get(conta.get(i)).remove(conta.get(i + 1)); listaRepetida2.get(conta.get(i)).remove(conta.get(i + 1));
// mesmo que a lista contenha objetos Integer // a JVM vai fazer o auto unboxing de Integer para int // pois a variável é do tipo int int posicao1 = conta.get(i); int posicao2 = conta.get(i + 1); listaRepetida2.get(posicao1).remove(posicao2); listaRepetida2.get(posicao1).remove(posicao2);
GOSTEI 0
Carlos Rocha
15/07/2013
Rapaz!
Não é que eu tinha feito esse teste antes de você postar e deu certo.
Segue a classe toda.
Se houver jeito de melhorar, me dá dica? Estou achando que esse monte de loops (i,j,k,l) pode ser melhorado mas não estou conseguindo achar a lógica.
import java.util.ArrayList;
public class RemoveRepetidas
{
ArrayList<ArrayList<Integer>> listaRepetida = new ArrayList<ArrayList<Integer>>();
RemoveRepetidas (ArrayList<ArrayList<Integer>> _listaRepetida)
{
this.listaRepetida = _listaRepetida;
}
String removeRepetida()
{
//System.out.println(this.listaRepetida);
ArrayList<Integer> conta = new ArrayList<Integer>();
ArrayList<ArrayList<Integer>> listaRepetida2 = listaRepetida;
for (int i = 0; i < listaRepetida2.size(); i++)
{
for (int j = i+1; j < listaRepetida2.size(); j++)
{
for (int k = 0; k < listaRepetida2.get(i).size(); k++)
{
for (int l = 0; l < listaRepetida2.get(j).size(); l++)
{
if (
( listaRepetida2.get(i).get(k) == listaRepetida2.get(j).get(l) && listaRepetida2.get(i).get(k+1) == listaRepetida2.get(j).get(l+1) ) ||
( listaRepetida2.get(i).get(k+1) == listaRepetida2.get(j).get(l) && listaRepetida2.get(i).get(k) == listaRepetida2.get(j).get(l+1) )
)
{
conta.add(j);
conta.add(l);
conta.add(l+1);
}
l++;
}
k++;
}
}
}
for (int i = 0; i < conta.size(); i++)
{
int a = conta.get(i+1);
int b = conta.get(i+2);
listaRepetida2.get(conta.get(i)).remove(a);
listaRepetida2.get(conta.get(i)).remove(b);
i+=2;
}
String texto = "{";
for (int i = 0; i < listaRepetida2.size(); i++)
{
for (int j = 0; j < listaRepetida2.get(i).size(); j++)
{
texto += listaRepetida2.get(i).get(j) + "," + listaRepetida2.get(i).get(j+1) + ",";
j++;
}
texto+= ",";
}
texto += "}";
texto = texto.replace(",,",",");
texto = texto.substring(0,(texto.length()-2)) + texto.substring(texto.length()-1) ;
return texto;
}
}
GOSTEI 0