Matrizes em Java: um guia de referência
1. Introdução
Neste tutorial, vamos nos aprofundar em um conceito central da linguagem Java - arrays.
Veremos primeiro o que é um array, depois como usá-los; em geral, vamos cobrir como:
-
Introdução às matrizes
-
Ler e gravar elementos de matrizes
-
Loop sobre uma matriz
-
Transforme matrizes em outros objetos comoList ouStreams
-
Classifique, pesquise e combine matrizes
2. O que é um Array?
Em primeiro lugar, precisamos definir o que é um array? De acordo comthe Java documentation, uma matriz éan object containing a fixed number of values of the same type. Os elementos de um array são indexados, o que significa que podemos acessá-los com números (chamadosindices).
Podemos considerar uma matriz como uma lista numerada de células, cada célula sendo uma variável com um valor. Em Java, a numeração começa em 0.
Existem matrizes de tipo primitivo e matrizes de tipo de objeto. Isso significa que podemos usar arrays deint, float, boolean, …, mas também arrays deString, Objecte tipos personalizados também.
3. Configurando uma matriz
Agora que os arrays estão bem definidos, vamos mergulhar em seus usos.
Cobriremos muitos tópicos nos ensinando como usar matrizes. Aprenderemos alguns princípios básicos, como declarar e inicializar uma matriz, mas também abordaremos assuntos mais avançados, como classificação e pesquisa de matrizes.
Vamos primeiro com a declaração e inicialização.
3.1. Declaração
Vamos começar com a declaração. Há duas maneiras de declarar uma matriz em Java:
int[] anArray;
or:
int anOtherArray[];
The former is more widely used than the latter.
3.2. Inicialização
Agora que é hora de ver como inicializar matrizes. Novamente, existem várias maneiras de inicializar uma matriz. Veremos os principais aqui, masthis article cobre a inicialização de matrizes em detalhes.
Vamos começar com uma maneira simples:
int[] anArray = new int[10];
Usando este método, inicializamos um array de dez elementosint. Observe que precisamos especificar o tamanho da matriz.
Ao usar este método,we initialize each element to its default value, aqui 0. Ao inicializar um array deObject, os elementos sãonull por padrão.
Agora veremos outra maneira que nos dá a possibilidade de definir valores para o array diretamente ao criá-lo:
int[] anArray = new int[] {1, 2, 3, 4, 5};
Aqui, inicializamos uma matriz de cinco elementos contendo os números de 1 a 5. Ao usar este método, não precisamos especificar o comprimento da matriz, é o número de elementos então declarado entre as chaves.
4. Acessando elementos
Vamos agora ver como acessar os elementos de um array. Podemos conseguir isso exigindo uma posição da célula da matriz.
Por exemplo, este pequeno trecho de código imprimirá 10 no console:
anArray[0] = 10;
System.out.println(anArray[0]);
Observe como estamos usando índices para acessar as células da matriz. The number between the brackets is the specific position of the array we want to access.
Ao acessar uma célula, se o índice passado for negativo ou ultrapassar a última célula, o Java lançará umArrayIndexOutOfBoundException.
Devemos ter cuidado entãonot to use a negative index, or an index greater than or equal to the array size.
5. Iterando sobre uma matriz
Acessar elementos um por um pode ser útil, mas podemos querer iterar por meio de uma matriz. Vamos ver como podemos conseguir isso.
A primeira maneira é usar o loopfor:
int[] anArray = new int[] {1, 2, 3, 4, 5};
for (int i = 0; i < anArray.length; i++) {
System.out.println(anArray[i]);
}
Isso deve imprimir os números de 1 a 5 no console. As we can see we made use of the length property. This is a public property giving us the size of the array.
Claro, é possível usar outros mecanismos de loop, comowhile oudo while. Mas, como para coleções Java, é possível fazer um loop em arrays usando o loopforeach:
int[] anArray = new int[] {1, 2, 3, 4, 5};
for (int element : anArray) {
System.out.println(element);
}
Este exemplo é equivalente ao anterior, mas nos livramos do código padrão do índice. The foreach loop is an option when:
-
não precisamos modificar a matriz (colocar outro valor em um elemento não modificará o elemento na matriz)
-
não precisamos dos índices para fazer outra coisa
6. Varargs
Já cobrimos o básico quando se trata da criação e manipulação de arrays. Agora, vamos mergulhar em tópicos mais avançados, começando comvarargs. Como um lembrete,varargs são usados para passar um número arbitrário de argumentos para um método:
void varargsMethod(String... varargs) {}
Este método pode levar de 0 a um número arbitrário de argumentosString. Um artigo cobrindovarargs pode ser encontradohere.
O que precisamos saber aqui é que dentro do corpo do método, um parâmetrovarargs se transforma em um array. Mas,we can also pass an array directly as the argument. Vamos ver como reutilizando o método de exemplo declarado acima:
String[] anArray = new String[] {"Milk", "Tomato", "Chips"};
varargsMethod(anArray);
Comportará-se da mesma maneira que:
varargsMethod("Milk", "Tomato", "Chips");
7. Transformando uma matriz em uma lista
Arrays são ótimos, mas às vezes pode ser mais prático lidar comList. Veremos aqui como transformar um array em umList.
Primeiro, faremos isso de maneira ingênua, criando uma lista vazia e iterando a matriz para adicionar seus elementos à lista:
int[] anArray = new int[] {1, 2, 3, 4, 5};
List aList = new ArrayList<>();
for (int element : anArray) {
aList.add(element);
}
Mas há outra maneira, um pouco mais sucinta:
Integer[] anArray = new Integer[] {1, 2, 3, 4, 5};
List aList = Arrays.asList(anArray);
The static method Arrays.asList takes a varargs argument and creates a list with the passed values. Infelizmente, esse método vem com algumas desvantagens:
-
Não é possível usar uma matriz de tipos primitivos
-
Não podemos adicionar ou remover elementos da lista criada, pois isso gerará umUnsupportedOperationException
8. De uma matriz para um fluxo
Agora podemos transformar arrays em listas, mas desde o Java 8 temos acesso aStream API e podemos querer transformar nossos arrays emStream. Java nos fornece o métodoArrays.stream para isso:
String[] anArray = new String[] {"Milk", "Tomato", "Chips"};
Stream aStream = Arrays.stream(anArray);
Ao passar um arrayObject para o método, ele retornará umStream do tipo correspondente (por exemplo Stream<Integer> para uma matriz deInteger). Ao passar um primitivo ele retornará o primitivo correspondenteStream.
Também é possível criar o stream apenas em um subconjunto da matriz:
Stream anotherStream = Arrays.stream(anArray, 1, 3);
Isso criará umStream<String> com apenas “Tomate” e “Chips”Strings (o primeiro índice sendo inclusivo, enquanto o segundo é exclusivo).
9. Classificando matrizes
Vamos agora ver como classificar um array, que está reorganizando seus elementos em uma determinada ordem. The Arrays class provides us with the sort method. Um pouco como o métodostream,sort tem muitas sobrecargas.
Existem sobrecargas para classificar:
-
Matrizes de tipo primitivo: classificadas em ordem crescente
-
MatrizesObject (aquelasObject devem implementar a interfaceComparable): que são classificadas de acordo com a ordem natural (dependendo do métodocompareTo deComparable)
-
Matrizes genéricas: que são classificadas de acordo com um determinadoComparator
Além disso, é possível classificar apenas uma parte específica de uma matriz (passando os índices inicial e final para o método).
Os algoritmos por trás do métodosort sãoquick sortemerge sort para matrizes primitivas e outras matrizes, respectivamente.
Vamos ver como tudo isso funciona por meio de alguns exemplos:
int[] anArray = new int[] {5, 2, 1, 4, 8};
Arrays.sort(anArray); // anArray is now {1, 2, 4, 5, 8}
Integer[] anotherArray = new Integer[] {5, 2, 1, 4, 8};
Arrays.sort(anotherArray); // anotherArray is now {1, 2, 4, 5, 8}
String[] yetAnotherArray = new String[] {"A", "E", "Z", "B", "C"};
Arrays.sort(yetAnotherArray, 1, 3,
Comparator.comparing(String::toString).reversed()); // yetAnotherArray is now {"A", "Z", "E", "B", "C"}
10. Pesquisando em uma matriz
Pesquisando um array é bastante simples, podemos fazer um loop sobre o array e pesquisar nosso elemento entre os elementos do array:
int[] anArray = new int[] {5, 2, 1, 4, 8};
for (int i = 0; i < anArray.length; i++) {
if (anArray[i] == 4) {
System.out.println("Found at index " + i);
break;
}
}
Aqui, pesquisamos o número 4 e o encontramos no índice 3.
If we have a sorted array though, we can use another solution: the binary search. O princípio da pesquisa binária é explicado emthis article.
Fortunately, Java provides us with the Arrays.binarySearch method. Temos que fornecer um array e um elemento para pesquisar.
No caso de um array genérico, também temos que dar a eleComparator que foi usado para ordenar o array em primeiro lugar. Há novamente a possibilidade de chamar o método em um subconjunto da matriz.
Vejamos um exemplo do uso do método de pesquisa binária:
int[] anArray = new int[] {1, 2, 3, 4, 5};
int index = Arrays.binarySearch(anArray, 4);
System.out.println("Found at index " + index);
Como armazenamos o número 4 na quarta célula, isso retornará o índice 3 como resultado. Observe que usamos uma matriz já classificada.
11. Concatenando matrizes
Finalmente, vamos ver como concatenar duas matrizes. The idea is to create an array which length is the sum of the two arrays to concatenate. Depois disso, temos queadd the elements of the first one and then the elements of the second one:
int[] anArray = new int[] {5, 2, 1, 4, 8};
int[] anotherArray = new int[] {10, 4, 9, 11, 2};
int[] resultArray = new int[anArray.length + anotherArray.length];
for (int i = 0; i < resultArray.length; i++) {
resultArray[i] = (i < anArray.length ? anArray[i] : anotherArray[i - anArray.length]);
}
Como podemos ver, quando o índice ainda é menor que o comprimento da primeira matriz, adicionamos elementos dessa matriz. Em seguida, adicionamos elementos do segundo. Podemos usar o métodoArrays.setAll para evitar a escrita de um loop:
int[] anArray = new int[] {5, 2, 1, 4, 8};
int[] anotherArray = new int[] {10, 4, 9, 11, 2};
int[] resultArray = new int[anArray.length + anotherArray.length];
Arrays.setAll(resultArray, i -> (i < anArray.length ? anArray[i] : anotherArray[i - anArray.length]));
Este método definirá todo o elemento da matriz de acordo com a função fornecida. Esta função associa um índice a um resultado.
Aqui está uma terceira opção para mesclar em matrizes:System.arraycopy. Este método leva uma fontearray, uma posição de origem, um destinoarray, uma posição de destino e umint definindo o número de elementos a copiar:
System.arraycopy(anArray, 0, resultArray, 0, anArray.length);
System.arraycopy(anotherArray, 0, resultArray, anArray.length, anotherArray.length);
Como podemos ver, copiamos o primeiro array, depois o segundo (após o último elemento do primeiro).
12. Conclusão
Neste artigo detalhado, cobrimos os usos básicos e alguns avançados de arrays em Java.
Vimos que Java oferece muitos métodos para lidar com matrizes por meio deArrays utility class. Também existem classes utilitárias para manipular matrizes em bibliotecas comoApache Commons ouGuava.
O código completo deste artigo pode ser encontrado emour GitHub.