Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Aprenda Estrutura de Dados Fila em Java | Estruturas de Dados Avançadas em Java
Estruturas de Dados em Java

bookEstrutura 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

Example.java

copy
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, retornando true se for bem-sucedido ou false caso 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

Main.java

copy
1234567891011121314
package 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

Main.java

copy
1234567891011121314
package 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, retornando null se 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

Main.java

copy
123456789101112131415
package 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

Main.java

copy
123456789101112131415
package 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

Main.java

copy
1234567891011121314151617181920
package 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

Main.java

copy
123456789101112131415161718
package 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, retornando null se 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

Main.java

copy
12345678910111213141516
package 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

Main.java

copy
123456789101112131415161718192021
package 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

Main.java

copy
1234567891011121314151617181920
package 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()?

question mark

O que é uma Queue em Java?

Select the correct answer

question mark

Qual interface representa uma Queue no Java Collections Framework?

Select the correct answer

question mark

Qual é o propósito do método offer() na interface Queue?

Select the correct answer

question mark

O que o método poll() faz na interface Queue?

Select the correct answer

question mark

Qual classe no pacote java.util.concurrent do Java representa uma fila bloqueante limitada?

Select the correct answer

question mark

O que acontece se você tentar adicionar um elemento a uma fila cheia usando o método add()?

Select the correct answer

Tudo estava claro?

Como podemos melhorá-lo?

Obrigado pelo seu feedback!

Seção 2. Capítulo 1

Pergunte à IA

expand

Pergunte à IA

ChatGPT

Pergunte o que quiser ou experimente uma das perguntas sugeridas para iniciar nosso bate-papo

bookEstrutura 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

Example.java

copy
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, retornando true se for bem-sucedido ou false caso 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

Main.java

copy
1234567891011121314
package 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

Main.java

copy
1234567891011121314
package 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, retornando null se 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

Main.java

copy
123456789101112131415
package 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

Main.java

copy
123456789101112131415
package 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

Main.java

copy
1234567891011121314151617181920
package 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

Main.java

copy
123456789101112131415161718
package 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, retornando null se 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

Main.java

copy
12345678910111213141516
package 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

Main.java

copy
123456789101112131415161718192021
package 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

Main.java

copy
1234567891011121314151617181920
package 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()?

question mark

O que é uma Queue em Java?

Select the correct answer

question mark

Qual interface representa uma Queue no Java Collections Framework?

Select the correct answer

question mark

Qual é o propósito do método offer() na interface Queue?

Select the correct answer

question mark

O que o método poll() faz na interface Queue?

Select the correct answer

question mark

Qual classe no pacote java.util.concurrent do Java representa uma fila bloqueante limitada?

Select the correct answer

question mark

O que acontece se você tentar adicionar um elemento a uma fila cheia usando o método add()?

Select the correct answer

Tudo estava claro?

Como podemos melhorá-lo?

Obrigado pelo seu feedback!

Seção 2. Capítulo 1
some-alt