Introdução
Na programação Java, trabalhar com diferentes estruturas de dados é essencial para o desenvolvimento eficiente de programas. Arrays e Lists são duas estruturas de dados fundamentais que servem a propósitos distintos. Enquanto arrays fornecem armazenamento de tamanho fixo, Lists oferecem flexibilidade com dimensionamento dinâmico e métodos utilitários adicionais.
Este tutorial foca na conversão de arrays Java em Lists mutáveis sem modificar os dados originais do array. Ao final deste laboratório, você entenderá a relação entre arrays e Lists e aprenderá técnicas práticas para converter entre eles, mantendo a integridade dos dados.
Compreendendo Arrays e Lists em Java
Nesta etapa, exploraremos as diferenças básicas entre arrays e Lists em Java, criando exemplos de ambos. Também examinaremos como acessar e exibir seus elementos.
Criando um Projeto Java
Vamos começar criando um arquivo Java simples para trabalhar:
Abra o terminal e navegue até o diretório do projeto:
cd ~/projectCrie um novo diretório para nossos arquivos Java:
mkdir -p src/main/java cd src/main/javaCrie um novo arquivo Java chamado
ArrayListDemo.javausando o WebIDE. Clique no ícone Explorer no WebIDE, navegue atéproject/src/main/java, clique com o botão direito e selecione "New File". Nomeie-o comoArrayListDemo.java.Adicione o seguinte código ao arquivo:
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
System.out.println("Java Arrays vs Lists Example");
System.out.println("============================");
// Creating an array of integers
int[] numbersArray = {1, 2, 3, 4, 5};
// Displaying array contents
System.out.println("Array contents: " + Arrays.toString(numbersArray));
// Accessing array elements by index
System.out.println("Array element at index 2: " + numbersArray[2]);
// Creating a List using ArrayList
List<Integer> numbersList = new ArrayList<>();
numbersList.add(1);
numbersList.add(2);
numbersList.add(3);
numbersList.add(4);
numbersList.add(5);
// Displaying list contents
System.out.println("List contents: " + numbersList);
// Accessing list elements by index
System.out.println("List element at index 2: " + numbersList.get(2));
// Demonstrating List flexibility - adding a new element
numbersList.add(6);
System.out.println("List after adding element: " + numbersList);
// Demonstrating List flexibility - removing an element
numbersList.remove(1); // Removes element at index 1
System.out.println("List after removing element at index 1: " + numbersList);
}
}
- Compile e execute o programa Java:
cd ~/project javac src/main/java/ArrayListDemo.java java -cp src/main/java ArrayListDemo
Você deve ver uma saída semelhante a esta:
Java Arrays vs Lists Example
============================
Array contents: [1, 2, 3, 4, 5]
Array element at index 2: 3
List contents: [1, 2, 3, 4, 5]
List element at index 2: 3
List after adding element: [1, 2, 3, 4, 5, 6]
List after removing element at index 1: [1, 3, 4, 5, 6]
Principais Diferenças entre Arrays e Lists
Flexibilidade de tamanho:
- Arrays têm um tamanho fixo que não pode ser alterado após a criação
- Lists podem crescer ou diminuir dinamicamente conforme necessário
Operações disponíveis:
- Arrays têm funcionalidade embutida limitada
- Lists fornecem inúmeros métodos para adicionar, remover e manipular elementos
Restrições de tipo:
- Arrays podem armazenar primitivos ou objetos
- Lists só podem armazenar objetos (mas o autoboxing permite armazenar primitivos indiretamente)
Compreender essas diferenças ajuda você a escolher a estrutura de dados certa para suas necessidades específicas.
Convertendo Arrays para Lists
Agora que entendemos os conceitos básicos de arrays e Lists, vamos explorar diferentes maneiras de converter um array em uma List. Focaremos particularmente na criação de Lists mutáveis a partir de arrays.
Crie um Novo Arquivo Java
Crie um novo arquivo Java chamado
ArrayToListConversion.javano mesmo diretório:No WebIDE, navegue até
project/src/main/java, clique com o botão direito e selecione "New File". Nomeie-o comoArrayToListConversion.java.Adicione o seguinte código ao arquivo:
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class ArrayToListConversion {
public static void main(String[] args) {
System.out.println("Converting Arrays to Lists");
System.out.println("=========================");
// Create an array of Strings
String[] fruitsArray = {"Apple", "Banana", "Cherry", "Date", "Elderberry"};
System.out.println("Original array: " + Arrays.toString(fruitsArray));
// Method 1: Using Arrays.asList() - Creates a fixed-size list
System.out.println("\nMethod 1: Arrays.asList()");
List<String> fruitsListFixed = Arrays.asList(fruitsArray);
System.out.println("List created with Arrays.asList(): " + fruitsListFixed);
// Try to modify the list
System.out.println("Changing element at index 0 to 'Apricot'");
fruitsListFixed.set(0, "Apricot");
System.out.println("List after change: " + fruitsListFixed);
System.out.println("Original array after List change: " + Arrays.toString(fruitsArray));
// This will cause UnsupportedOperationException
try {
System.out.println("Trying to add a new element to the fixed-size list...");
fruitsListFixed.add("Fig");
} catch (UnsupportedOperationException e) {
System.out.println("Error: Cannot add to fixed-size list!");
}
// Reset the array for next example
fruitsArray[0] = "Apple";
// Method 2: Using new ArrayList<>(Arrays.asList()) - Creates a mutable list
System.out.println("\nMethod 2: new ArrayList<>(Arrays.asList())");
List<String> fruitsList = new ArrayList<>(Arrays.asList(fruitsArray));
System.out.println("List created with new ArrayList<>(Arrays.asList()): " + fruitsList);
// Modify the list
System.out.println("Adding 'Fig' to the list");
fruitsList.add("Fig");
System.out.println("List after adding 'Fig': " + fruitsList);
System.out.println("Original array after List modification: " + Arrays.toString(fruitsArray));
// Method 3: Using Stream API (Java 8+)
System.out.println("\nMethod 3: Using Stream API");
List<String> fruitsListStream = Arrays.stream(fruitsArray)
.collect(Collectors.toList());
System.out.println("List created with Stream API: " + fruitsListStream);
// Modify the list
System.out.println("Adding 'Grape' to the list");
fruitsListStream.add("Grape");
System.out.println("List after adding 'Grape': " + fruitsListStream);
System.out.println("Original array after List modification: " + Arrays.toString(fruitsArray));
}
}
- Compile e execute o programa:
cd ~/project javac src/main/java/ArrayToListConversion.java java -cp src/main/java ArrayToListConversion
Você deve ver uma saída semelhante a esta:
Converting Arrays to Lists
=========================
Original array: [Apple, Banana, Cherry, Date, Elderberry]
Method 1: Arrays.asList()
List created with Arrays.asList(): [Apple, Banana, Cherry, Date, Elderberry]
Changing element at index 0 to 'Apricot'
List after change: [Apricot, Banana, Cherry, Date, Elderberry]
Original array after List change: [Apricot, Banana, Cherry, Date, Elderberry]
Trying to add a new element to the fixed-size list...
Error: Cannot add to fixed-size list!
Method 2: new ArrayList<>(Arrays.asList())
List created with new ArrayList<>(Arrays.asList()): [Apple, Banana, Cherry, Date, Elderberry]
Adding 'Fig' to the list
List after adding 'Fig': [Apple, Banana, Cherry, Date, Elderberry, Fig]
Original array after List modification: [Apple, Banana, Cherry, Date, Elderberry]
Method 3: Using Stream API
List created with Stream API: [Apple, Banana, Cherry, Date, Elderberry]
Adding 'Grape' to the list
List after adding 'Grape': [Apple, Banana, Cherry, Date, Elderberry, Grape]
Original array after List modification: [Apple, Banana, Cherry, Date, Elderberry]
Compreendendo os Diferentes Métodos de Conversão
Arrays.asList():
- Cria uma lista de tamanho fixo apoiada pelo array original
- O tamanho da lista não pode ser alterado (sem adicionar/remover elementos)
- As alterações nos elementos da lista afetam o array original
new ArrayList<>(Arrays.asList()):
- Cria um novo ArrayList que contém todos os elementos do array
- A lista é mutável (pode adicionar/remover elementos)
- As alterações na lista não afetam o array original
Stream API (Java 8+):
- Uma abordagem mais moderna usando programação funcional
- Cria uma lista completamente independente
- Oferece flexibilidade para realizar transformações durante a conversão
Para iniciantes, o segundo método (new ArrayList<>(Arrays.asList())) é geralmente o mais útil porque cria uma lista totalmente mutável sem afetar o array original.
Trabalhando com Arrays Primitivos
Nas etapas anteriores, trabalhamos com arrays de tipos de referência (String). No entanto, os arrays Java também podem conter tipos primitivos como int, double, etc. Converter arrays primitivos para Lists requer etapas adicionais porque os generics Java só funcionam com tipos de referência.
Vamos criar um novo exemplo para demonstrar este processo.
Crie um Novo Arquivo Java
Crie um novo arquivo Java chamado
PrimitiveArrayToList.javano mesmo diretório:No WebIDE, navegue até
project/src/main/java, clique com o botão direito e selecione "New File". Nomeie-o comoPrimitiveArrayToList.java.Adicione o seguinte código ao arquivo:
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class PrimitiveArrayToList {
public static void main(String[] args) {
System.out.println("Converting Primitive Arrays to Lists");
System.out.println("===================================");
// Create a primitive int array
int[] numbersArray = {10, 20, 30, 40, 50};
System.out.println("Original primitive array: " + Arrays.toString(numbersArray));
// Method 1: Manual conversion
System.out.println("\nMethod 1: Manual conversion");
List<Integer> numbersList1 = new ArrayList<>();
for (int number : numbersArray) {
numbersList1.add(number); // Autoboxing converts int to Integer
}
System.out.println("List after manual conversion: " + numbersList1);
// Method 2: Using Java 8 Streams
System.out.println("\nMethod 2: Using Java 8 Streams");
List<Integer> numbersList2 = Arrays.stream(numbersArray)
.boxed() // Converts IntStream to Stream<Integer>
.collect(Collectors.toList());
System.out.println("List after stream conversion: " + numbersList2);
// Modify the lists to demonstrate independence from the array
System.out.println("\nModifying the lists:");
numbersList1.add(60);
numbersList1.set(0, 15);
numbersList2.add(70);
numbersList2.remove(0);
System.out.println("List 1 after modifications: " + numbersList1);
System.out.println("List 2 after modifications: " + numbersList2);
System.out.println("Original array after List modifications: " + Arrays.toString(numbersArray));
// Create and convert other primitive type arrays
System.out.println("\nOther primitive type examples:");
double[] doubleArray = {1.1, 2.2, 3.3, 4.4, 5.5};
List<Double> doubleList = Arrays.stream(doubleArray)
.boxed()
.collect(Collectors.toList());
System.out.println("Double array: " + Arrays.toString(doubleArray));
System.out.println("Double list: " + doubleList);
boolean[] boolArray = {true, false, true, true, false};
List<Boolean> boolList = new ArrayList<>();
for (boolean value : boolArray) {
boolList.add(value);
}
System.out.println("Boolean array: " + Arrays.toString(boolArray));
System.out.println("Boolean list: " + boolList);
}
}
- Compile e execute o programa:
cd ~/project javac src/main/java/PrimitiveArrayToList.java java -cp src/main/java PrimitiveArrayToList
Você deve ver uma saída semelhante a esta:
Converting Primitive Arrays to Lists
===================================
Original primitive array: [10, 20, 30, 40, 50]
Method 1: Manual conversion
List after manual conversion: [10, 20, 30, 40, 50]
Method 2: Using Java 8 Streams
List after stream conversion: [10, 20, 30, 40, 50]
Modifying the lists:
List 1 after modifications: [15, 20, 30, 40, 50, 60]
List 2 after modifications: [20, 30, 40, 50, 70]
Original array after List modifications: [10, 20, 30, 40, 50]
Other primitive type examples:
Double array: [1.1, 2.2, 3.3, 4.4, 5.5]
Double list: [1.1, 2.2, 3.3, 4.4, 5.5]
Boolean array: [true, false, true, true, false]
Boolean list: [true, false, true, true, false]
Compreendendo a Conversão de Arrays Primitivos
Ao trabalhar com arrays primitivos, há duas considerações principais:
Autoboxing: Java converte automaticamente valores primitivos em seus objetos de classe wrapper ao adicionar a coleções. Por exemplo,
inté convertido emInteger.Métodos de Boxing para Streams: Ao usar streams com arrays primitivos, você precisa chamar o método
.boxed()para converter streams primitivos em streams de objetos.
O processo de conversão cria Lists completamente novas que são independentes dos arrays originais. Isso significa:
- Modificar a List não afetará o array original
- As Lists são totalmente mutáveis (você pode adicionar, remover ou alterar elementos)
- Cada elemento na List é um novo objeto (wrapper) que contém o valor do array
Essa independência é particularmente útil quando você precisa manipular os dados sem arriscar alterações no array original.
Aplicações Práticas e Armadilhas Comuns
Agora que entendemos como converter arrays em Lists mutáveis, vamos explorar algumas aplicações práticas e armadilhas comuns. Criaremos um exemplo final que demonstra casos de uso do mundo real e como evitar erros comuns.
Crie um Novo Arquivo Java
Crie um novo arquivo Java chamado
ArrayListPractical.javano mesmo diretório:No WebIDE, navegue até
project/src/main/java, clique com o botão direito e selecione "New File". Nomeie-o comoArrayListPractical.java.Adicione o seguinte código ao arquivo:
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
public class ArrayListPractical {
public static void main(String[] args) {
System.out.println("Practical Applications and Common Pitfalls");
System.out.println("========================================");
// Use case 1: Creating a mutable list from a configuration array
String[] defaultSettings = {"dark-mode", "auto-save", "notifications"};
System.out.println("Default settings array: " + Arrays.toString(defaultSettings));
// Create a mutable list of user settings starting with defaults
List<String> userSettings = new ArrayList<>(Arrays.asList(defaultSettings));
System.out.println("Initial user settings list: " + userSettings);
// User can add or remove settings
userSettings.add("sync-enabled");
userSettings.remove("notifications");
System.out.println("Modified user settings: " + userSettings);
System.out.println("Original default settings (unchanged): " + Arrays.toString(defaultSettings));
// Use case 2: Working with legacy APIs that return arrays
System.out.println("\nUse case: Working with legacy APIs");
// Simulate a legacy API that returns an array
String[] legacyData = getLegacyData();
System.out.println("Data from legacy API (array): " + Arrays.toString(legacyData));
// Convert to a mutable list for modern processing
List<String> modernData = new ArrayList<>(Arrays.asList(legacyData));
// Process with modern methods
modernData.removeIf(item -> item.startsWith("OLD_"));
modernData.replaceAll(item -> item.toLowerCase());
System.out.println("Processed data (list): " + modernData);
// Common Pitfall 1: Forgetting that Arrays.asList creates a fixed-size list
System.out.println("\nCommon Pitfall 1: Fixed-size list");
Integer[] numberArray = {1, 2, 3, 4, 5};
// This creates a fixed-size list
List<Integer> wrongWay = Arrays.asList(numberArray);
System.out.println("Fixed-size list: " + wrongWay);
try {
wrongWay.add(6); // This will fail
} catch (UnsupportedOperationException e) {
System.out.println("Error: Cannot add to fixed-size list!");
}
// Correct way
List<Integer> rightWay = new ArrayList<>(Arrays.asList(numberArray));
rightWay.add(6); // This works fine
System.out.println("Mutable list: " + rightWay);
// Common Pitfall 2: Array of primitives
System.out.println("\nCommon Pitfall 2: Array of primitives");
int[] primitiveArray = {10, 20, 30};
// This won't compile: Arrays.asList(primitiveArray)
// List<Integer> primitiveList = Arrays.asList(primitiveArray);
// Correct ways
List<Integer> primitiveList1 = new ArrayList<>();
for (int value : primitiveArray) {
primitiveList1.add(value);
}
List<Integer> primitiveList2 = Arrays.stream(primitiveArray)
.boxed()
.toList();
System.out.println("Primitive array: " + Arrays.toString(primitiveArray));
System.out.println("Converted list (loop method): " + primitiveList1);
System.out.println("Converted list (stream method): " + primitiveList2);
}
// Simulate a legacy API that returns an array
private static String[] getLegacyData() {
return new String[] {"OLD_RECORD1", "ACTIVE_DATA", "OLD_RECORD2", "CURRENT_INFO"};
}
}
- Compile e execute o programa:
cd ~/project javac src/main/java/ArrayListPractical.java java -cp src/main/java ArrayListPractical
Você deve ver uma saída semelhante a esta:
Practical Applications and Common Pitfalls
========================================
Default settings array: [dark-mode, auto-save, notifications]
Initial user settings list: [dark-mode, auto-save, notifications]
Modified user settings: [dark-mode, auto-save, sync-enabled]
Original default settings (unchanged): [dark-mode, auto-save, notifications]
Use case: Working with legacy APIs
Data from legacy API (array): [OLD_RECORD1, ACTIVE_DATA, OLD_RECORD2, CURRENT_INFO]
Processed data (list): [active_data, current_info]
Common Pitfall 1: Fixed-size list
Fixed-size list: [1, 2, 3, 4, 5]
Error: Cannot add to fixed-size list!
Mutable list: [1, 2, 3, 4, 5, 6]
Common Pitfall 2: Array of primitives
Primitive array: [10, 20, 30]
Converted list (loop method): [10, 20, 30]
Converted list (stream method): [10, 20, 30]
Principais Conclusões das Aplicações Práticas
Gerenciamento de Configuração: Usar arrays para configurações padrão e Lists para configurações específicas do usuário permite flexibilidade, preservando os padrões.
Trabalhando com APIs Legadas: Muitas APIs Java mais antigas retornam arrays, que você pode converter em Lists para aproveitar os recursos modernos do Java, como expressões lambda e referências de métodos.
Armadilhas Comuns a Evitar:
- Lembre-se que
Arrays.asList()cria uma lista de tamanho fixo que não pode crescer ou diminuir - Arrays primitivos não podem ser passados diretamente para
Arrays.asList()- você deve usar loops ou streams com boxing
- Lembre-se que
Melhor Prática: Para a maioria dos casos de uso, a abordagem mais segura é usar
new ArrayList<>(Arrays.asList(array))para arrays de objetos e métodos de stream para arrays primitivos.
Ao entender esses padrões e armadilhas, você pode trabalhar efetivamente com arrays e Lists em seus aplicativos Java, escolhendo a estrutura de dados e o método de conversão corretos para cada situação.
Resumo
Neste laboratório, você aprendeu como criar Lists mutáveis a partir de arrays Java, preservando os dados do array original. Você explorou:
As diferenças fundamentais entre arrays e Lists Java, incluindo sua estrutura, capacidades e casos de uso.
Múltiplos métodos para converter arrays em Lists:
- Usando
Arrays.asList()para uma visão de tamanho fixo do array - Usando
new ArrayList<>(Arrays.asList())para uma List totalmente mutável - Usando a API Stream com
.boxed()para arrays primitivos
- Usando
Considerações especiais para arrays primitivos, que exigem boxing explícito para converter em Lists de objetos wrapper.
Aplicações práticas e armadilhas comuns ao trabalhar com arrays e Lists, incluindo gerenciamento de configuração e interação com APIs legadas.
Essas técnicas são valiosas em muitas aplicações Java do mundo real, onde você precisa trabalhar com arrays e Lists, particularmente quando você precisa preservar dados originais enquanto cria coleções flexíveis e mutáveis para manipulação. Compreender a relação entre arrays e Lists permite que você escreva um código Java mais eficiente e sustentável.



