Arrays e Matrizes
Tags: estruturadedados, java, array, matriz
Published: 2023-04-10 19:09:39

Olá! Hoje vamos ver um pouco sobre arrays e matrizes, abordando os seguintes tópicos:

{% details Sumário %}
- 1. Introdução
  - 1.1 O que são?
  - 1.2 Para quê serve?
  - 1.3 Como se faz?
- 2. Características
  - 2.1 Armazenamento contíguo de elemento
  - 2.2 Acesso indexado aos elementos
  - 2.3 Tamanho fixo
  - 2.4 Armazenamento bidimensional
- 3. Aplicabilidade
  - 3.1 Situação Acadêmica
  - 3.2 Situação Real
- 4. Conclusão
{% enddetails %}


Espero que goste e qualquer coisa é só mandar feedback.

=================================================

## 1. Introdução

Certo dia estava num aplicativo de mensagens quando eu vi status (acabei de entregar o app kkkk) de uma pessoa vendo um conteúdo sobre Vetores e matrizes, daí eu tive uma ideia de elaborar um conteúdo sobre isso sobre uma perspectiva de aplicabilidade acadêmica e de mercado. Sem mais delongas, vamos logo começar isso.

### 1.1 O que são?

Se você está chegando aqui sem nenhuma ideia do que são essas coisas, vou te dá primeiro a definição. suave? Bora lá.

> matrizes e vetores são estruturas de dados que permitem o armazenamento de um conjunto de valores em uma única variável
>
> *Definição Acadêmica*

Essa definição é interessante, creio que podemos ficar com ela. "Ah, mas eu não sei o que é estrutura de dados!", então lá vai uma explicação rápida: São formas de guardar e organizar informações em um computador. Pronto, agora você sabe o que é... pelo menos tem noção do que é kkkk.

### 1.2 Para quê serve?

Matrizes e arrays são um tipo de mecanismo para organizar e manipular dados de maneira organizada, logo, é uma forma .

Você pode até pensar: "Mas não é tão simples assim na prática, não é possível", vamos lá... o nível de dificuldade de aplicabilidade pode ser maior a depender do problema que enfrentamos, entretanto, em termo conceitual, é isso.

"Mas Lucas, eu preciso de algo mais específico para cada um.", ok, vou te ajudar nessa.

**Arrays**: São usados para armazenar vários valores do mesmo tipo em uma lista ordenada, onde cada valor é identificado por um índice numérico.

**Matrizes**: São como arrays multidimensionais, ou seja, são usadas para armazenar valores em uma tabela com duas ou mais dimensões.

Matrizes geralmente são mais complicadas de se entender geralmente, mas vamos ver isso melhor com o decorrer do post, então vem comigo.

### 1.3 Como se faz?

Para esse post utilizarei Java, mas você é livre para tentar usar os exemplos na linguagem de preferência.

Exemplo_1: Você está elaborando um sisteminha para o gerenciamento de pessoas que foram convidadas para o casamento de um parente bem próximo seu (você está sendo pago). Você está programando tranquilamente, até que se depara com um estresse gigantesco, precisa fazer uma lista de nomes das pessoas que irão comparecer e depois imprimir no console 1 por 1. Em tese irão comparecer 5 pessoas (ciclo social pequeno).

Vamos para ideias de implementação...

Primeira ideia:

![ideia_1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jjknntxzo2o44yr8rza0.png)

Essa ideia não é legal, estamos ferindo o princípio de não se repetir, estamos criando variáveis de maneira exacerbada explicitamente. Será que não tem alguma ideia mais interessante?

Segunda ideia:

![ideia_2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dmhu0fdebun1wuwofs6y.png)

"MINHA NOSSA, NÃO ENTENDI ABSOLUTAMENTE NADA DO QUE VOCÊ FEZ!!!", o intuito é realmente você não entender tudo assim de cara, agora vamos destrinchar o que foi feito.

Começaremos a entender as coisas a partir da linha 5, nela temos `String convidados[] = new String[5]` que significa que estamos criando uma espécie de caixinha que contém 5 strings, "caixinhas? Quê??", calma, basicamente o código está indicando para a memória criar 5 espaços internos para a variável convidados.

Uma analogia a esse tipo de compreensão é imaginar que você chega em uma pessoa que faz bolos para entrega. Provavelmente a primeira pergunta que ela irá fazer a você é a quantidade de pessoas que irão comer, logo o tamanho do bolo será proporcional a quantidade. É semelhante a isso que é a estrutura de declaração de arrays, você informa o tipo e a quantidade.

Da linha 6 à linha 8 você pode perceber que ocorre atribuição de valores para cada posição conforme a imagem abaixo.

![imagem_memoria](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gjuwxj3ifg3hhucse4e1.png)

"Pera... começa no 0? Por quê????"

A origem do uso da indexação começando em 0 nos arrays é amplamente atribuída ao linguista e cientista da computação dinamarquês Kristen Nygaard, co-inventor da linguagem de programação Simula, que introduziu essa convenção nos primeiros relatórios técnicos da linguagem Simula 67, publicados em 1967.

Outra possível razão para o uso de índices baseados em 0 é que eles permitem que as fórmulas para calcular o endereço de memória de um elemento sejam mais simples e eficientes, pois não há necessidade de adicionar um deslocamento à base do endereço. Essa escolha também pode ter sido influenciada por convenções matemáticas que usam índices baseados em 0.

Vale ressaltar que nem todas as linguagens de programação usam índices baseados em 0 para arrays, algumas usam base 1 ou outras convenções.

Iniciando a análise do código, em nosso `for` podemos ver duas coisas bem interessantes, o `convidados.length` que serve para pegar o tamanho total do array, no caso 5. O segundo fator a ser observado é dentro do sysout, onde temos `convidados[i]`, ou seja, pegue o convidado que esteja na posição i.

> **OBS**: Poderia ser um foreach, mas pode ser que alguém queira implementar em outra linguagem que não tenha esse recurso, então vai puro mesmo.

## 2. Características

Tudo na área de tecnologia possui particularidades, isso serve para paradigmas como [orientação a objetos](https://dev.to/lucas_jdev/orientacao-a-objetos-4nkk), programação funcional, programação reativa etc. Dessa forma, podemos começar a falar sobre alguns pontos característicos.

### 2.1 Armazenamento contíguo de elemento

Quando dizemos que elementos estão armazenados contiguamente em um array ou matriz, isso significa que os elementos são armazenados em locais de memória adjacentes, um após o outro. Isso é importante porque permite que o acesso aos elementos seja rápido e eficiente.

"Eu meio que entendi, mas você pode me fornecer algum exemplo didático?" bora lá.

Situação:
Imagine que você tem uma prateleira com uma coleção de livros. Se você organizar os livros em ordem alfabética e deixar um espaço vazio entre cada livro, pode ser difícil encontrar um livro específico rapidamente. Mas, se você colocar todos os livros juntos em ordem alfabética, sem deixar espaços vazios, será mais fácil encontrar o livro que está procurando.

Isso é semelhante ao armazenamento contíguo em arrays e matrizes.

Além disso, o armazenamento contíguo também torna mais fácil para o processador acessar os elementos do array ou matriz. Isso ocorre porque o processador pode acessar uma região contígua de memória de uma só vez, em vez de precisar buscar elementos em diferentes locais da memória. É como se o processador pudesse pegar um grupo de livros da prateleira de uma só vez, em vez de precisar pegar um livro de cada vez em locais diferentes.

Louco né? Eu não sei você, mas acho isso sensacional.

### 2.2 Acesso indexado aos elementos

Para entender melhor como funciona o acesso indexado, vamos voltar ao exemplo dos livros na prateleira. Se você organizou seus livros em ordem alfabética e sem espaços vazios, você pode encontrar um livro específico rapidamente usando a primeira letra do título como referência. Por exemplo, se você quiser encontrar o livro "Dom Casmurro", você pode ir direto à seção "D" da prateleira e procurar pelo livro.

Caso você não consiga visualizar isso na sua mente, é basicamente assim:

![fluxograma_pratileira](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qifj3aev7gzuxbz6c0iq.png)

Em um array ou matriz, o índice ou posição funciona da mesma forma que a primeira letra do título do livro. Cada elemento do array ou matriz é armazenado em uma posição específica, que é identificada por um índice ou posição. Por exemplo, em um array de números inteiros, o primeiro elemento é armazenado na posição 0, o segundo na posição 1, o terceiro na posição 2 e assim por diante.

Quando queremos acessar um elemento específico do array ou matriz, usamos o índice ou posição correspondente. Por exemplo, se quisermos acessar o terceiro elemento de um array de números inteiros, usamos o índice 2, que corresponde à posição 2 do array.

O acesso indexado é importante porque nos permite acessar elementos específicos de um array ou matriz de forma rápida e eficiente. Em vez de percorrer todos os elementos do array ou matriz em busca de um elemento específico, podemos ir direto à posição correspondente usando o índice ou posição.

### 2.3 Tamanho fixo

Um array ou matriz com tamanho fixo é aquele que possui uma quantidade pré-definida de elementos. Esse tamanho não pode ser alterado durante a execução do programa, ou seja, ele é fixo desde o momento em que o array ou matriz é criado.

Uma analogia para entender o conceito de tamanho fixo é a de uma caixa de sapatos. Imagine que você precisa organizar uma coleção de sapatos em casa e decide usar caixas de sapato para armazená-los. Se você escolher caixas de tamanhos diferentes, pode ter problemas para armazenar os sapatos de maneira organizada e eficiente. Por outro lado, se você escolher caixas de tamanho fixo, poderá acomodar cada par de sapatos de forma ordenada e padronizada, sem desperdiçar espaço.

De maneira similar, ao usar arrays ou matrizes com tamanho fixo, podemos garantir que todos os elementos serão armazenados de forma organizada e padronizada, ocupando um espaço de memória conhecido e previsível. Isso torna mais fácil o acesso e manipulação dos elementos, pois não precisamos nos preocupar com variações no tamanho do array ou matriz.

No entanto, é importante ressaltar que o tamanho fixo pode limitar a flexibilidade do programa. Se precisarmos armazenar mais elementos do que o tamanho fixo permite, será necessário criar um novo array ou matriz com um tamanho maior e copiar os elementos do array anterior. Isso pode gerar um overhead de memória e processamento.

### 2.4 Armazenamento bidimensional

Uma maneira de entender o armazenamento bidimensional é imaginar uma tabela ou uma planilha. Se você já trabalhou com uma planilha eletrônica, como o Excel, sabe que ela é organizada em células, que formam uma grade bidimensional com linhas e colunas. Cada célula pode armazenar um valor, como um número, um texto ou uma fórmula.

Da mesma forma, em uma matriz bidimensional, os elementos são organizados em uma grade com linhas e colunas. Cada elemento é identificado por um par de índices, um para a linha e outro para a coluna. Por exemplo, em uma matriz com 3 linhas e 4 colunas, podemos acessar o elemento da segunda linha e terceira coluna usando os índices (1, 2).

Uma analogia para entender a organização bidimensional das matrizes é imaginar um tabuleiro de xadrez. O tabuleiro é uma matriz com 8 linhas e 8 colunas, onde cada célula pode conter uma peça de xadrez ou estar vazia. Cada célula é identificada por um par de índices, que correspondem à linha e coluna da célula.

O armazenamento bidimensional permite que as matrizes sejam usadas para representar informações que possuem uma estrutura de grade, como imagens, tabelas, mapas, entre outras. Além disso, as operações matemáticas com matrizes, como a multiplicação de matrizes, também são baseadas no armazenamento bidimensional.

## 3. Aplicabilidade

Uma coisa muito comum é estudantes de programação não saberem como aplicar arrays ou matrizes na vida acadêmica e em aplicações reais, então para solucionar esse pequeno probleminha - pelo menos tentar - vou te mostrar algumas situações acadêmicas e reais.

### 3.1 Situação acadêmica

"Capture do teclado valore para o preenchimento de uma matriz M 3x3. Após a captura imprima a matriz criada e encontre a quantidade de números pares e a quantidade de números ímpares."

Há variadas formas de resolver esse problema, mas eu proponho a seguinte solução:

```Java
import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    int[][] matriz = new int[3][3];
    int pares = 0, impares = 0;

    // Captura os valores do teclado para preencher a matriz
    for (int linha = 0; linha < matriz.length; linha++) {
      for (int coluna = 0; coluna < matriz[linha].length; coluna++) {
        System.out.print("Digite o valor da posição [" + linha + "][" + coluna + "]: ");
        matriz[linha][coluna] = scanner.nextInt();
      }
    }

    // Imprime a matriz criada
    System.out.println("\nMatriz criada:");
    for (int linha = 0; linha < matriz.length; linha++) {
      for (int coluna = 0; coluna < matriz[linha].length; coluna++) {
        System.out.print(matriz[linha][coluna] + "\t");
      }
      System.out.println();
    }

    // Conta a quantidade de números pares e ímpares na matriz
    for (int linha = 0; linha < matriz.length; linha++) {
      for (int coluna = 0; coluna < matriz[linha].length; coluna++) {
        if (matriz[linha][coluna] % 2 == 0) {
          pares++;
        } else {
          impares++;
        }
      }
    }

    // Imprime a quantidade de números pares e ímpares na matriz
    System.out.println("\nQuantidade de números pares na matriz: " + pares);
    System.out.println("Quantidade de números ímpares na matriz: " + impares);
  }
}
```

Para algumas pessoas pode ser um código muito complexo, e sim, tem sua complexidade, alegar que não há complexidade em `for` encadeado é uma mentira. Você pode tentar entender esse código com mais calma depois, pois isso daqui é apenas uma exemplificação de aplicabilidade acadêmica.

### 3.2 Situação Real

"Você está de cara para um sistema antigo de uma empresa chamada 'Betinho construção', nessa aplicação você precisa implementar no banco de dados e retornar apenas os 100 únicos clientes que essa empresa pode ter"

Bom... eu não vou implementar aqui seguindo as melhores práticas de isolamento de responsabilidades como o SRP, mesmo porque eu só quero que você tenha uma noção de quando utilizar pode utilizar.

Segue a minha solução:

```Java
public class ClienteDAO {
  public Cliente[] buscaClientes() {
    try {
      // Conecta ao banco de dados
      Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/meubanco", "usuario", "senha");

      // Busca todos os clientes da tabela
      Statement stmt = conn.createStatement();
      ResultSet rs = stmt.executeQuery("SELECT * FROM clientes");

      // Cria um array de objetos Cliente e preenche com os registros obtidos do banco de dados
      Cliente[] clientes = new Cliente[100]; // Suponha que a tabela tem no máximo 100 registros
      int i = 0;
      while (rs.next()) {
        int id = rs.getInt("id");
        String nome = rs.getString("nome");
        int idade = rs.getInt("idade");
        Cliente cliente = new Cliente(id, nome, idade);
        clientes[i++] = cliente;
      }

      // Fecha a conexão com o banco de dados
      conn.close();

      //retorna todos os clientes buscados
      return clientes;
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }
}
``` 

Como você pode ver, eis um exemplo hipotético de como isso pode funcionar em um caso da vida real.

"Ah Lucas, mas hoje em dia há outras estruturas como p `ArrayList`, `HashSet` etc, então por quê iria ter isso na vida real?". Há muitos casos em que o nível técnico de alguém pode não está adaptado ao problema disposto, mas mesmo assim entregar uma solução. Acontece, não estou dizendo que a pessoa é uma má programadora, estou dizendo que pode haver um déficit técnico no projeto e cabe a você entender o cenário antes de corrigir alguma coisa.

## 4. Conclusão

Pronto, vimos o que é, para que serve, quando usar, quais contextos pode encontrar etc. Esse é um pequeno estudo apesar de você ainda achar ele longo, tentei ser o mais didático possível, espero que você tenha sucesso nos estudos e é isso. A gente se vê em outro post.


**Bibliografia**:
FERREIRA, Nickerson. Aula 01 - Vetores e Matrizes. Disponível em: http://docente.ifrn.edu.br/nickersonferreira/disciplinas/programacao-estruturada-e-orientada-a-objetos/aula-01-vetores-e-matrizes/view. Acesso em: 04 abr. 2023.
SILVA, Vinícius Gusmão Pereira da. Estrutura de dados. São Paulo: Novatec Editora, 2013.