[RESOLVIDO]Dúvida com vetores

22 respostas
R

Boa tarde, pessoal.
Estou tentando fazer um programa que mostra uma matriz de números inteiros mas não estou conseguindo fazer. Na verdade é um teste para um programa que lê um arquivo de texto que contém números em forma de tabela de 6 colunas e um valor indefinido de linhas. Por eu não saber de antemão o número de linhas que terei que alocar, usei um ArrayList para ir armazenando dinamicamente os vetores de tamanho 6, pois sei que o arquivo terá sempre seis colunas, mas na hora de mostrar não está dando certo. Abaixo, coloquei o código, espero que possam me ajudar.

package MatrizTeste;

import java.util.ArrayList;

public class MatrizTeste
{

      public static void main(String[] args)
      {
            int coluna[] = new int[6];
            ArrayList linha = new ArrayList();
            try
            {
                  for (int i = 0; i < 4; i++)
                  {
                        for (int j = 0; j < coluna.length; j++)
                        {
                              coluna[j] = j * 3;
                        }
                        linha.add(coluna);
                  }
                  for (int i = 0; i < 4; i++)
                  {
                        for (int j = 0; j < coluna.length; j++)
                        {
                              System.out.print(linha.get(coluna[j]) + " ");
                        }
                        System.out.println();
                  }
            } catch (java.lang.IndexOutOfBoundsException exc)
            {
                  System.out.println("Erro com endereço do vetor.");
            }
      }
}

Obrigado.

22 Respostas

Arthur_F_Ferreira

Eu reescrevi seu código com os comentários onde foram feitas alterações explicando cada coisa:

public static void main(String[] args) {
        // Ao invés de colocar os colchetes na variável, coloque no tipo.
        int[] coluna = new int[6];

        // Trabalhe com a interface List ao invés da implementação e defina o tipo da lista. Se você estiver usando o Java 7, no ArrayList basta usar o diamond.
        List<int[]> linha = new ArrayList<>();
        try {
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < coluna.length; j++) {
                    coluna[j] = j * 3;
                }
                linha.add(coluna);

                // Você precisa criar um novo vetor com os valores das colunas para a nova linha
                coluna = new int[6];
            }
            
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < coluna.length; j++) {
                    // Aqui você vai pegar a linha de índice 'i' e a coluna de índice 'j'
                    System.out.print(linha.get(i)[j] + " ");
                }
                System.out.println();
            }
        } catch (java.lang.IndexOutOfBoundsException exc) {
            System.out.println("Erro com endereço do vetor.");
        }
    }
R

Arthur F. Ferreira:
Eu reescrevi seu código com os comentários onde foram feitas alterações explicando cada coisa:

public static void main(String[] args) {
        // Ao invés de colocar os colchetes na variável, coloque no tipo.
        int[] coluna = new int[6];

        // Trabalhe com a interface List ao invés da implementação e defina o tipo da lista. Se você estiver usando o Java 7, no ArrayList basta usar o diamond.
        List<int[]> linha = new ArrayList<>();
        try {
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < coluna.length; j++) {
                    coluna[j] = j * 3;
                }
                linha.add(coluna);

                // Você precisa criar um novo vetor com os valores das colunas para a nova linha
                coluna = new int[6];
            }
            
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < coluna.length; j++) {
                    // Aqui você vai pegar a linha de índice 'i' e a coluna de índice 'j'
                    System.out.print(linha.get(i)[j] + " ");
                }
                System.out.println();
            }
        } catch (java.lang.IndexOutOfBoundsException exc) {
            System.out.println("Erro com endereço do vetor.");
        }
    }

Muito obrigado, funcinou!
Tenho algumas dúvidas a respeito do código que você fez.

1- Faz alguma diferença se eu usar “int coluna[]” ao invés de “int[] coluna” ?

2- Porque devo usar List no lugar de ArrayList? Li que ArrayList implementa Lits como vetor, que é o que eu quero, então porque devo usar List?

3- Diamond é esse negócio aqui “< >”? Olhei no google mas não entendo quase nada Inglês!

4- Em “coluna = new int[6];” existe algum método onde eu possa liberar para a memória explicitamente o antigo vetor coluna?
Tipo em c++ com o método “free(coluna)” ?

Obrigado.

Arthur_F_Ferreira

Ok, vamos por partes

Para o compilador, não faz diferença. Porém, o normal é colocar os colchetes no tipo. Afinal de contas, quando você lê “int[]” você entende que é um vetor de inteiros. Quando você lê “coluna[]” você supostamente leria vetor de colunas. Fica esquisito, não?

Esse List é a interface java.util.List. Todas as listas em java implementam essa interface. Ou seja, se no futuro você decidir, por algum motivo, que ao invés de ArrayList você precisa usar LinkedList, basta você mudar o código para:

List<int[]> linha = new LinkedList<>();

Se você trabalhar com a implementação direto, talvez você tenha que alterar mais coisas no seu código, justamente por causa da diferença entre implementações. Por isso é melhor usar a interface do que a implementação.

Sim, isso é o diamond. Antes da versão 7, era recomendado que você colocasse o tipo também na construção:

List<int[]> linha = new LinkedList<int[]>();

Na versão 7 do java isso não é mais necessário e agiliza um pouquinho o desenvolvimento.

4- Em “coluna = new int[6];” existe algum método onde eu possa liberar para a memória explicitamente o antigo vetor coluna?
Tipo em c++ com o método “free(coluna)” ?

Ter, tem. Mas não será necessário. Diferente de C++, o java trabalha com referências aos objetos. Quando você fez:

linha.add(coluna);

Você copiou a referência que estava na variável “coluna” e passou para a última posição disponível na sua lista. Ou seja, cada posição da sua lista tem uma referência diferente para objetos diferentes na memória, por isso você não precisa dar nenhum free ou dispose na memória, porque todos os objetos continuam sendo utilizados e com referências. Mesmo porque, se não estiverem, o Garbage Collector se encarrega de dar o dispose.

R
Obrigado pela ajuda, cara. Uma última dúvida, por favor. Com faço para definir a matriz como atributo de classe e instanciar ela em um construtor? Tentei inúmeras formas de declaração e nehuma funcionou, a última que tentei foi essa que coloquei abaixo.
public class Historico {

      List matriz;// Se eu puser List<int[]> matriz, o Netbeans diz que List "does not take parametres".
      
      public Historico() 
      {
            this.matriz = new ArrayList<int[]>();//Isso também não funciona, a mensagem é required: List, found: ArrayList<int[]>
      }
}

Obrigado.

Arthur_F_Ferreira

Nos seus imports, qual é o pacote da lista? Deveria ser java.util.list. Muitas vezes há uma confusão com java.awt.list

E

Não é exatamente confusão.
É o vício da programação NNF (Next, Next, Finish).
É que quando ele tecla Ctrl+Shift+O no Eclipse (ou a tecla equivalente no NetBeans) a primeira opção que aparece para List é java.awt.List, em vez de java.util.List (é uma coisa que eu gostaria que fosse consertada tanto no NetBeans quanto no Eclipse). E o pessoal pega sempre a primeira opção :frowning:

Arthur_F_Ferreira

Ele lista em ordem alfabética, portanto, awt vem antes de util rs. Com o tempo você se acostuma e já vai buscar por útil ao invés de ir na sede do enter.

ViniGodoy

Arthur F. Ferreira:
4- Em “coluna = new int[6];” existe algum método onde eu possa liberar para a memória explicitamente o antigo vetor coluna?
Tipo em c++ com o método “free(coluna)” ?

Ter, tem. Mas não será necessário. Diferente de C++, o java trabalha com referências aos objetos. Quando você fez:

Só corrigindo. Não, não tem. No Java não existe nenhuma maneira de excluir explicitamente um objeto da memória e, mais difícil ainda, é de desalocar a memória utilizada pela VM. O máximo que você pode fazer é remover todas as referências de um objeto, o que torna ele elegível para garbage collection (e, para efeitos práticos, isso costuma a ser suficiente). Entretanto, você nunca sabe quando o gargabe collector vai rodar e se, quando rodar, ele vai efetivamente liberar aquele espaço de memória. Existe a possibilidade de dar uma “dica” para o gc rodar, através do comendo System.gc(), mas ele não é obrigado a obedecer esse comando. É importante entender que a VM mantém, ela mesma, um heap. Esse heap cresce a medida que o Java precisa de memória e é virtualmente impossível reduzi-lo através de comandos da linguagem.

E corrigindo também a parte de C++. Não se usa free em C++, e sim, o comando delete.

delete [] array;

free é coisa da linguagem C.

Arthur_F_Ferreira

E eu achava que era dispose rs. Há anos que não vejo/manipulo um código em C/C++

Valeu pela correção!

ViniGodoy

Arthur F. Ferreira:
E eu achava que era dispose rs. Há anos que não vejo/manipulo um código em C/C++

Valeu pela correção!

O dispose() não faz isso. O que ele faz é pedir ao objeto que libere os recursos que esteja segurando, e que não são responsabilidade do gc (é, no fundo, equivalente ao close, com a diferença de que o gc() chama esse método automaticamente durante a coleta). Exemplos de recursos são: uma conexão socket, um arquivo, ou recursos do ambiente de janelas, etc… nesse método, você fecharia o socket ou o arquivo. Mas o dispose() em si não dispara o garbage collector. =(

No caso do Swing, por exemplo, o dispose() libera widgets que o Swing possa ter alocado no SO, mas não coleta o “lado java” do objeto. Por isso, mesmo após um dispose() o Swing é capaz de tornar uma janela visível novamente (e recriar todos os widgets, como se nunca tivessem sido desalocados).

R
Arthur F. Ferreira:
Nos seus imports, qual é o pacote da lista? Deveria ser java.util.list. Muitas vezes há uma confusão com java.awt.list
Eu importei java.util.list. Olhando a conversa de vocês, notei que ninguém me ajudou na pergunta:
robgeek:
Obrigado pela ajuda, cara. Uma última dúvida, por favor. Com faço para definir a matriz como atributo de classe e instanciar ela em um construtor? Tentei inúmeras formas de declaração e nehuma funcionou, a última que tentei foi essa que coloquei abaixo.
public class Historico {

      List matriz;// Se eu puser List<int[]> matriz, o Netbeans diz que List "does not take parametres".
      
      public Historico() 
      {
            this.matriz = new ArrayList<int[]>();//Isso também não funciona, a mensagem é required: List, found: ArrayList<int[]>
      }
}

Obrigado.

Agradeço muito se me ajudarem.

Arthur_F_Ferreira

Mas quando eu perguntei se era java.util.List ou java.awt.List é justamente para te ajudar com esses problemas. Não era para o Netbeans reclamar deles, pelo contrário.

R

Vou tentar denovo aqui. Então a declaração que eu fiz ali está correta?
Já te respondo se funcionou no Netbeans, e aí, fecho o tópico.

R

Funcinou, mas aí eu criei uma classe main para instanciar o objeto historico e colocar o código que você corrigiu para mim e deu um erro. A classe main ficou assim:

public class Main
{
      public static void main(String[] args)
      {
            Historico historico = new Historico();
            int[] coluna = new int[6];
            try
            {
                  for (int i = 0; i < 4; i++)
                  {
                        for (int j = 0; j < coluna.length; j++)
                        {
                              coluna[j] = j * 3;
                        }
                        historico.linha.add(coluna);
                        coluna = new int[6];
                  }

                  for (int i = 0; i < 4; i++)
                  {
                        for (int j = 0; j < coluna.length; j++)
                        {
                              // Aqui deu erro o Netbeans disse "array required but Object found"  
                              System.out.print(historico.linha.get(i)[j] + " ");
                        }
                        System.out.println();
                  }
            } catch (java.lang.IndexOutOfBoundsException exc)
            {
                  System.out.println("Erro com endereço do vetor.");
            }
      }
}
Arthur_F_Ferreira

Cola aqui agora a sua classe Histórico.

R
Arthur F. Ferreira:
Cola aqui agora a sua classe Histórico.
public class Historico
{

      List linha;

      public Historico()
      {
            this.linha = new ArrayList<int[]>();
      }

      void mostra_matriz()
      {
            for (int i = 0; i < 4; i++)
            {
                  for (int j = 0; j < 6; j++)
                  {
                        // Aqui deu erro o Netbeans disse "array required but Object found"  
                        //System.out.print(linha.get(i)[j] + " ");
                  }
                  System.out.println();
            }
      }
}

E aqui a classe main que instancia e chama o método de Historico.

public class Main
{
      public static void main(String[] args)
      {
            Historico historico = new Historico();
            int[] coluna = new int[6];
            try
            {
                  for (int i = 0; i < 4; i++)
                  {
                        for (int j = 0; j < 6; j++)
                        {
                              coluna[j] = j * 3;
                        }
                        historico.linha.add(coluna);
                        coluna = new int[6];
                  }
			// Chama o método para mostrar a matriz, mas dá erro!
                  historico.mostra_matriz();

            } catch (java.lang.IndexOutOfBoundsException exc)
            {
                  System.out.println("Erro com endereço do vetor.");
            }
      }
}
Arthur_F_Ferreira

Quando você trabalha com a interface List você tem que dizer o tipo da lista, se não, o java vai supor que é um Object. Aí, você precisaria fazer casting para funcionar corretamente. Portanto, altere seu código na classe Historico para:

List<int[]> linha;
R

Nossa cara, isso é muito estranho! Eu jurava que tinha tentado isso antes e o Netbenas não compilava. Agora fiz isso que você disse e funcinou.
Sei que já estou abusando do tópico mas queria te perguntar uma última coisa já até coloquei resovido no título dele.

Não consigo entender como o método “get()”, abaixo funciona!

System.out.print(linha.get(i)[j] + " ");

Isso é parte de um programinha que mostra uma matriz de números inteiros na tela. A matriz é declarada da seguinte forma:

List<int[]> linha = new ArrayList<>();

O que entendi e sei que está errado, é que o método “get()” retorna o valor que está contido no endereço “i” que recebe como parâmetro. Mas a parte que não faz sentido é que para mostrar uma matriz normal, do tipo, “int[][] linha;” o código seria:

System.out.print(linha[endereço i][endereço j]);

Só que no método que tenho dúvida, por causa do método “get()”, ficaria assim:

System.out.print(linha[valor contido no endereço i][endereço j]);

O que não faz sentido para mim! Não sei se você entendeu minha dúvida, sinceramente espero que sim.

Obrigado.

Arthur_F_Ferreira

Para melhorar a sua compreensão, o método get que faz parte da interface List não retorna o valor que está contido no endereço “i”…

Ele retorna o valor que está contido na posição “i” da lista.

Se você trabalha com um vetor de duas dimensões, é exatamente como você disse. Quando você faz

System.out.println(linha[i][j]);

Você está dizendo que quer o vetor da posição “i” da primeira dimensão e o valor da posição “j” do vetor recuperado.

Ficou mais claro?

R

E o que o “j” em :

linha.get(i)[i];

dentro destes colchetes está fazendo ali, então? Desculpa, cara, eu só não queria escrever este método sem saber como ele funciona, mas está um tanto confuso.

Arthur_F_Ferreira

Vou tentar simplificar a leitura. Esse código:

System.out.println(linha.get(i)[j]);

É a mesma coisa que:

// Você recupera o vetor na posição "i" da sua lista.
int[] vetor = linha.get(i);
// Depois você imprime o valor inteiro da posição "j" do seu vetor.
System.out.println(vetor[j]);

Entendeu?

R

Arthur F. Ferreira:
Vou tentar simplificar a leitura. Esse código:

System.out.println(linha.get(i)[j]);

É a mesma coisa que:

// Você recupera o vetor na posição "i" da sua lista.
int[] vetor = linha.get(i);
// Depois você imprime o valor inteiro da posição "j" do seu vetor.
System.out.println(vetor[j]);

Entendeu?

AAAAA taaaaaa, agora sim, cara!
Pô, muito mais fácil de entender deste jeito. Caramba, obrigado pela sua paciência em me ajudar nestas questões.

Obrigado mesmo.

Tópico encerradom, então :slight_smile:

Criado 26 de dezembro de 2012
Ultima resposta 27 de dez. de 2012
Respostas 22
Participantes 4