Estrutura de Dados Fila em Java
Vamos começar com uma Queue. Imagine uma fila em uma loja durante uma promoção. Há 10 pessoas; a primeira pessoa está mais próxima das portas da loja do que as outras, e a décima pessoa está mais distante. Quando a primeira pessoa entra na loja, ela sai da fila, fazendo com que toda a fila avance uma posição. A Queue em Java funciona de maneira muito semelhante.
Dessa forma, é possível implementar diversos programas onde a lógica de fila é bem estruturada. Por exemplo, implementar um quadro com planos e tarefas.
Mas antes, vamos analisar os métodos básicos para trabalhar com uma Queue.
Queue é uma interface da qual a classe LinkedList herda, com a qual você já está familiarizado, então utilizaremos essa implementação.
Dessa forma, utiliza-se a interface como o tipo do objeto, mas a implementação do objeto será LinkedList, pois é uma implementação específica desse objeto. (Lembre-se de que não é possível criar objetos a partir de uma interface).
Exemplo:
Example.java
1234// `LinkedList` as implementation of the `List` interface: List<T> list = new LinkedList<>(); // `LinkedList` as implementation of the `Queue` interface: Queue<T> queue = new LinkedList<>();
Dessa forma, é possível tornar a aplicação muito flexível ao utilizar várias implementações da mesma interface.
Mas vamos voltar aos métodos de trabalho com Queue.
Métodos
Alguns métodos principais da interface Queue são:
add(element): adiciona um elemento à fila, lançando uma exceção se a operação não for possível;offer(element): adiciona um elemento à fila, retornandotruese for bem-sucedido oufalsecaso contrário.
É possível notar que esses métodos basicamente fazem a mesma coisa. No entanto, a principal diferença está na segurança do método offer. Em caso de elemento adicionado de forma inadequada, o método offer não lançará uma exceção e não interromperá a execução do programa.
Porém, no momento, essa característica não é de grande interesse, pois uma Queue comum não possui limitações. No entanto, existe uma estrutura chamada BlockingQueue, que possui uma restrição quanto ao número de elementos; nesse caso, esses métodos terão uma diferença perceptível.
Vamos analisar um exemplo:
Main.java
1234567891011121314package com.example; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class Main { public static void main(String[] args) { BlockingQueue<String> queue = new LinkedBlockingQueue<>(2); queue.add("One"); queue.add("Two"); queue.add("Three"); System.out.println("Queue: " + queue); } }
Como pode ser observado, ao utilizar o método add() e tentar adicionar um elemento que não cabe na fila, o programa lança um erro, encerrando a execução de forma inesperada.
Vamos tentar a mesma operação, mas com um método mais seguro — offer():
Main.java
1234567891011121314package com.example; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class Main { public static void main(String[] args) { BlockingQueue<String> queue = new LinkedBlockingQueue<>(2); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); System.out.println("Queue: " + queue); } }
Como você pode ver, agora o elemento não foi adicionado à fila, mas também não lançou uma exceção. Portanto, podemos considerar que tratamos o erro de forma adequada.
Você pode tratar exceções de maneira diferente usando uma estrutura como try-catch, mas discutiremos isso mais adiante.
Métodos de Remoção
remove(): remove e retorna o elemento do início da fila, lançando uma exceção se a fila estiver vazia;poll(): remove e retorna o elemento do início da fila, retornandonullse a fila estiver vazia.
Esses métodos realizam exatamente a função como se a primeira pessoa da fila entrasse na loja e saísse da fila. É aqui que o princípio FIFO (First In, First Out) entra em ação. Ou seja, o elemento que foi adicionado primeiro à fila será o primeiro a ser removido.
Aqui, você também pode observar a diferença entre esses dois métodos. O método poll() é utilizado com mais frequência do que o método remove() porque é mais seguro e não lança exceções.
Vamos analisar um exemplo:
Main.java
123456789101112131415package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); System.out.println("Queue: " + queue); queue.remove(); queue.remove(); System.out.println("Queue after removal operation: " + queue); } }
Como pode ser observado, o programa lança uma NoSuchElementException porque estamos tentando remover um elemento de uma fila vazia.
Para evitar essa exceção, é melhor utilizar o método poll():
Main.java
123456789101112131415package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); System.out.println("Queue: " + queue); queue.poll(); queue.poll(); System.out.println("Queue after removal operation: " + queue); } }
Agora, um elemento foi removido da fila de forma segura, e nenhuma exceção foi lançada ao tentar remover um elemento de uma lista vazia.
O recurso do poll() retornar null pode ser utilizado, por exemplo, em um laço while().
Veja um exemplo:
Main.java
1234567891011121314151617181920package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); while (queue.poll() != null) { queue.poll(); } System.out.println("Queue after removal operation: " + queue); } }
Dessa forma, é possível remover todos os elementos da fila utilizando um loop.
Lembre-se de que o primeiro elemento que entrou na fila é o que será removido! Por exemplo, no caso do exemplo acima, o elemento com o dado "One" foi removido primeiro.
O princípio FIFO é demonstrado abaixo:
Main.java
123456789101112131415161718package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); queue.poll(); System.out.println("Queue after removal operation: " + queue); } }
Podemos avançar para os métodos que retornam o primeiro e o último elementos:
element(): retorna, mas não remove, o elemento do início da fila, lançando uma exceção se a fila estiver vazia;peek(): retorna, mas não remove, o elemento do início da fila, retornandonullse a fila estiver vazia.
Utilizar o método peek() é uma abordagem mais confiável e segura, pois ajuda a evitar possíveis exceções.
Veja um exemplo de uso:
Main.java
12345678910111213141516package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); System.out.println("Queue: " + queue); System.out.println("The first element in the queue: " + queue.peek()); System.out.println("Queue after the `peek()` method: " + queue); } }
É possível combinar este método com outros métodos da fila.
Se houver uma fila com cinco elementos e for necessário remover todos os elementos até o quarto (inclusive), veja a implementação dessa operação:
Main.java
123456789101112131415161718192021package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); while (!queue.peek().equals("Four")) { queue.poll(); } queue.poll(); System.out.println("Queue after removal operation: " + queue); } }
Você utilizou um loop com uma condição baseada no método peek().
É possível otimizar significativamente esse loop utilizando o método contains(). Esse método retorna true se o elemento especificado estiver presente na fila e false caso não esteja.
Vamos melhorar o código acima:
Main.java
1234567891011121314151617181920package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); while (queue.contains("Four")) { queue.poll(); } System.out.println("Queue after removal operation: " + queue); } }
Aqui, definimos uma única condição para o while loop. Conseguimos remover com sucesso todos os elementos até e incluindo o elemento "Four".
1. O que é uma Queue em Java?
2. Qual interface representa uma Queue no Java Collections Framework?
3. Qual é o propósito do método offer() na interface Queue?
4. O que o método poll() faz na interface Queue?
5. Qual classe no pacote java.util.concurrent do Java representa uma fila bloqueante limitada?
6. O que acontece se você tentar adicionar um elemento a uma fila cheia usando o método add()?
Obrigado pelo seu feedback!
Pergunte à IA
Pergunte à IA
Pergunte o que quiser ou experimente uma das perguntas sugeridas para iniciar nosso bate-papo
Can you explain more about the difference between add() and offer() methods?
How does the FIFO principle work in a real-world queue?
What are some practical uses of the Queue interface in Java?
Incrível!
Completion taxa melhorada para 4
Estrutura de Dados Fila em Java
Deslize para mostrar o menu
Vamos começar com uma Queue. Imagine uma fila em uma loja durante uma promoção. Há 10 pessoas; a primeira pessoa está mais próxima das portas da loja do que as outras, e a décima pessoa está mais distante. Quando a primeira pessoa entra na loja, ela sai da fila, fazendo com que toda a fila avance uma posição. A Queue em Java funciona de maneira muito semelhante.
Dessa forma, é possível implementar diversos programas onde a lógica de fila é bem estruturada. Por exemplo, implementar um quadro com planos e tarefas.
Mas antes, vamos analisar os métodos básicos para trabalhar com uma Queue.
Queue é uma interface da qual a classe LinkedList herda, com a qual você já está familiarizado, então utilizaremos essa implementação.
Dessa forma, utiliza-se a interface como o tipo do objeto, mas a implementação do objeto será LinkedList, pois é uma implementação específica desse objeto. (Lembre-se de que não é possível criar objetos a partir de uma interface).
Exemplo:
Example.java
1234// `LinkedList` as implementation of the `List` interface: List<T> list = new LinkedList<>(); // `LinkedList` as implementation of the `Queue` interface: Queue<T> queue = new LinkedList<>();
Dessa forma, é possível tornar a aplicação muito flexível ao utilizar várias implementações da mesma interface.
Mas vamos voltar aos métodos de trabalho com Queue.
Métodos
Alguns métodos principais da interface Queue são:
add(element): adiciona um elemento à fila, lançando uma exceção se a operação não for possível;offer(element): adiciona um elemento à fila, retornandotruese for bem-sucedido oufalsecaso contrário.
É possível notar que esses métodos basicamente fazem a mesma coisa. No entanto, a principal diferença está na segurança do método offer. Em caso de elemento adicionado de forma inadequada, o método offer não lançará uma exceção e não interromperá a execução do programa.
Porém, no momento, essa característica não é de grande interesse, pois uma Queue comum não possui limitações. No entanto, existe uma estrutura chamada BlockingQueue, que possui uma restrição quanto ao número de elementos; nesse caso, esses métodos terão uma diferença perceptível.
Vamos analisar um exemplo:
Main.java
1234567891011121314package com.example; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class Main { public static void main(String[] args) { BlockingQueue<String> queue = new LinkedBlockingQueue<>(2); queue.add("One"); queue.add("Two"); queue.add("Three"); System.out.println("Queue: " + queue); } }
Como pode ser observado, ao utilizar o método add() e tentar adicionar um elemento que não cabe na fila, o programa lança um erro, encerrando a execução de forma inesperada.
Vamos tentar a mesma operação, mas com um método mais seguro — offer():
Main.java
1234567891011121314package com.example; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class Main { public static void main(String[] args) { BlockingQueue<String> queue = new LinkedBlockingQueue<>(2); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); System.out.println("Queue: " + queue); } }
Como você pode ver, agora o elemento não foi adicionado à fila, mas também não lançou uma exceção. Portanto, podemos considerar que tratamos o erro de forma adequada.
Você pode tratar exceções de maneira diferente usando uma estrutura como try-catch, mas discutiremos isso mais adiante.
Métodos de Remoção
remove(): remove e retorna o elemento do início da fila, lançando uma exceção se a fila estiver vazia;poll(): remove e retorna o elemento do início da fila, retornandonullse a fila estiver vazia.
Esses métodos realizam exatamente a função como se a primeira pessoa da fila entrasse na loja e saísse da fila. É aqui que o princípio FIFO (First In, First Out) entra em ação. Ou seja, o elemento que foi adicionado primeiro à fila será o primeiro a ser removido.
Aqui, você também pode observar a diferença entre esses dois métodos. O método poll() é utilizado com mais frequência do que o método remove() porque é mais seguro e não lança exceções.
Vamos analisar um exemplo:
Main.java
123456789101112131415package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); System.out.println("Queue: " + queue); queue.remove(); queue.remove(); System.out.println("Queue after removal operation: " + queue); } }
Como pode ser observado, o programa lança uma NoSuchElementException porque estamos tentando remover um elemento de uma fila vazia.
Para evitar essa exceção, é melhor utilizar o método poll():
Main.java
123456789101112131415package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); System.out.println("Queue: " + queue); queue.poll(); queue.poll(); System.out.println("Queue after removal operation: " + queue); } }
Agora, um elemento foi removido da fila de forma segura, e nenhuma exceção foi lançada ao tentar remover um elemento de uma lista vazia.
O recurso do poll() retornar null pode ser utilizado, por exemplo, em um laço while().
Veja um exemplo:
Main.java
1234567891011121314151617181920package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); while (queue.poll() != null) { queue.poll(); } System.out.println("Queue after removal operation: " + queue); } }
Dessa forma, é possível remover todos os elementos da fila utilizando um loop.
Lembre-se de que o primeiro elemento que entrou na fila é o que será removido! Por exemplo, no caso do exemplo acima, o elemento com o dado "One" foi removido primeiro.
O princípio FIFO é demonstrado abaixo:
Main.java
123456789101112131415161718package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); queue.poll(); System.out.println("Queue after removal operation: " + queue); } }
Podemos avançar para os métodos que retornam o primeiro e o último elementos:
element(): retorna, mas não remove, o elemento do início da fila, lançando uma exceção se a fila estiver vazia;peek(): retorna, mas não remove, o elemento do início da fila, retornandonullse a fila estiver vazia.
Utilizar o método peek() é uma abordagem mais confiável e segura, pois ajuda a evitar possíveis exceções.
Veja um exemplo de uso:
Main.java
12345678910111213141516package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); System.out.println("Queue: " + queue); System.out.println("The first element in the queue: " + queue.peek()); System.out.println("Queue after the `peek()` method: " + queue); } }
É possível combinar este método com outros métodos da fila.
Se houver uma fila com cinco elementos e for necessário remover todos os elementos até o quarto (inclusive), veja a implementação dessa operação:
Main.java
123456789101112131415161718192021package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); while (!queue.peek().equals("Four")) { queue.poll(); } queue.poll(); System.out.println("Queue after removal operation: " + queue); } }
Você utilizou um loop com uma condição baseada no método peek().
É possível otimizar significativamente esse loop utilizando o método contains(). Esse método retorna true se o elemento especificado estiver presente na fila e false caso não esteja.
Vamos melhorar o código acima:
Main.java
1234567891011121314151617181920package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); while (queue.contains("Four")) { queue.poll(); } System.out.println("Queue after removal operation: " + queue); } }
Aqui, definimos uma única condição para o while loop. Conseguimos remover com sucesso todos os elementos até e incluindo o elemento "Four".
1. O que é uma Queue em Java?
2. Qual interface representa uma Queue no Java Collections Framework?
3. Qual é o propósito do método offer() na interface Queue?
4. O que o método poll() faz na interface Queue?
5. Qual classe no pacote java.util.concurrent do Java representa uma fila bloqueante limitada?
6. O que acontece se você tentar adicionar um elemento a uma fila cheia usando o método add()?
Obrigado pelo seu feedback!