Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Aprenda Prática de Fila | Estruturas de Dados Adicionais
Estruturas de Dados em Java

bookPrática de Fila

Prática

É hora de praticar. Você recebeu a tarefa de escrever um serviço TaskManager que vai controlar suas tarefas. Com este serviço, o usuário pode adicionar tarefas, atribuí-las a si mesmo e depois completá-las em uma ordem sequencial. Vamos começar a trabalhar nesta tarefa juntos, e depois você continuará por conta própria.

Nota

Neste exercício, usaremos a estrutura de interface-implementação. Primeiramente, vamos escrever uma interface que vai definir os métodos a serem implementados pelas classes herdeiras.

Mas primeiro, precisamos criar o próprio modelo de tarefa. Vamos criar uma classe Task:

main.java

main.java

copy
12345
public class Task { private int id; private String name; private String description; }

A classe Task contém 3 atributos: id, name e description. Cada tarefa deve ter um nome e descrição, e o id é um atributo necessário para qualquer estrutura de dados. Como mais nós acessaríamos os elementos? Os atributos também são protegidos por o modificador de acesso private, pois não queremos que outras classes tenham acesso direto aos campos desta classe, exceto através do construtor ou getters.

Agora, vamos implementar esses getters e o construtor. Isso pode ser facilmente feito usando a combinação das teclas control + return em um MacBook.

Após as operações realizadas, temos a seguinte classe Task:

Task.java

Task.java

copy
12345678910111213141516171819202122232425262728293031323334
package codefinity.taskManager; public class Task { private int id; private String name; private String description; public Task(int id, String name, String description) { this.id = id; this.name = name; this.description = description; } public int getId() { return id; } public String getName() { return name; } public String getDescription() { return description; } @Override public String toString() { return "Task{" + "id=" + id + ", name='" + name + '\'' + ", description='" + description + '\'' + '}'; } }

Serviços

Teremos um serviço de quadro de tarefas muito simplificado, por isso vamos implementar um serviço que irá adicionar, marcar como concluídas, e verificar se há tarefas na fila. Vamos chamar essa classe de TaskQueueService. Para começar, precisamos definir uma interface com essas tarefas:

TaskQueueService.TaskQueueService

TaskQueueService.TaskQueueService

copy
123456789
package codefinity.taskManager; public interface TaskQueueService { void addTask(Task task); Task getNextTask(); boolean isEmpty(); }

Esta interface define 3 métodos que as classes de implementação devem implementar. Esses métodos incluem adicionar uma tarefa, passar para a próxima tarefa (o que implica que o usuário já completou a tarefa anterior), e um método para verificar se existem tarefas na fila.

Ótimo, vamos agora criar uma classe de implementação que irá sobrescrever e implementar todos esses métodos:

TaskQueueServiceImpl.TaskQueueServiceImpl

TaskQueueServiceImpl.TaskQueueServiceImpl

copy
12345678910
package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.Task; import java.util.LinkedList; import java.util.Queue; public class TaskQueueServiceImpl { private Queue<Task> taskQueue = new LinkedList<>(); }

Criamos um atributo private que será utilizado apenas nesta classe de serviço.

Vale a pena fazer uma pequena digressão e falar sobre classes de serviço, que são uma parte distinta da POO. Classes de serviço são criadas para realizar operações específicas. Elas herdam de interfaces de serviço e implementam seus métodos. Essa abordagem para escrever uma aplicação ajuda a manter e estender a mesma, seguindo os princípios SOLID, os quais estudaremos em um curso separado. No momento, é importante entender que tais classes são criadas exclusivamente para realizar operações em outros objetos.

Por exemplo: Se escrevermos uma calculadora, teremos uma classe separada que armazenará o valor do número em que operamos. As operações de fato serão realizadas usando uma classe de serviço onde adição, subtração e assim por diante são definidos.

Espero que isso esclareça a função das classes de serviço na resolução da tarefa em questão.

Implementação do Serviço

Vamos continuar a execução da tarefa. O próximo passo é demonstrar que essa classe implementa a interface TaskQueueService. Para isso, utilizamos a palavra-chave implements e especificamos a interface que a classe implementa. Também precisamos sobrescrever os métodos definidos pela interface. O IntelliJ IDEA ainda nos permite simplificar significativamente essa tarefa utilizando a combinação option + return.

Agora, em nossa classe, todos os métodos que precisam ser sobrescritos são mostrados. Vamos em frente e façamos isso!

TaskQueueServiceImpl.java

TaskQueueServiceImpl.java

copy
1234567891011121314151617181920212223242526
package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.Task; import codefinity.taskManager.TaskQueueService; import java.util.LinkedList; import java.util.Queue; public class TaskQueueServiceImpl implements TaskQueueService { private Queue<Task> taskQueue = new LinkedList<>(); @Override public void addTask(Task task) { taskQueue.offer(task); } @Override public Task getNextTask() { return taskQueue.poll(); } @Override public boolean isEmpty() { return taskQueue.isEmpty(); } }

No nosso caso, nada excessivamente complicado foi feito. Simplesmente utilizamos os métodos da classe Queue para implementar nossos métodos corretamente. Assim, uma estrutura de dados como a fila facilita a vida de todos os programadores Java.

Usamos o método offer() para adicionar, o método poll() para remover e o método isEmpty() para verificar se a fila está vazia.

Agora é a sua vez de desempenhar um papel na resolução deste problema. Você precisará implementar uma classe de serviço, cuja interface criaremos juntos:

main.java

main.java

copy
12345
package codefinity.taskManager; public interface TaskProcessorService { void processTasks(); }

Criamos uma interface de serviço com um método: processTasks(), que, quando invocado, deve começar a executar todas as tarefas até que a lista de tarefas esteja vazia. Esse método representa um usuário começando a realizar tarefas.

Nota

Se você quiser tornar a tarefa um pouco mais desafiadora, você pode adicionar um método para processar uma única tarefa. Nesse caso, você precisa criar um método separado, processTask(), nesta interface. Este método deve processar a primeira tarefa da lista.

Tarefa

Sua tarefa é escrever uma classe TaskProcessorServiceImpl que deve implementar a interface TaskProcessorService. Esta classe deve ter um método para processar todas as tarefas, o que significa que deve usar métodos do serviço TaskQueueService. Você pode usar composição criando uma instância desta classe dentro da classe que você precisa implementar, por exemplo:

main.java

main.java

copy
1234567
package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.TaskQueueService; public class TaskProcessorServiceImpl { TaskQueueService taskQueueService = new TaskQueueServiceImpl(); }

Em geral, já existe uma composição preparada no topo para sua tarefa. Em seguida, você só precisa implementar um método usando uma instância desta classe.

Depois disso, você precisa criar um construtor que inicializará este objeto da classe taskQueueService.

Deste modo, você poderá usar os métodos deste objeto. Também é evidente que, para o processamento de tarefas, você precisa passar a fila com a qual o taskProcessor vai trabalhar.

O restante da tarefa fica por sua conta. Dicas serão fornecidas no arquivo README.md. Uma vez que sua solução estiver pronta, clique no botão "Executar Testes", e os testes unitários que escrevi verificarão sua solução.

Tudo estava claro?

Como podemos melhorá-lo?

Obrigado pelo seu feedback!

Seção 2. Capítulo 3

Pergunte à IA

expand

Pergunte à IA

ChatGPT

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

Awesome!

Completion rate improved to 4

bookPrática de Fila

Deslize para mostrar o menu

Prática

É hora de praticar. Você recebeu a tarefa de escrever um serviço TaskManager que vai controlar suas tarefas. Com este serviço, o usuário pode adicionar tarefas, atribuí-las a si mesmo e depois completá-las em uma ordem sequencial. Vamos começar a trabalhar nesta tarefa juntos, e depois você continuará por conta própria.

Nota

Neste exercício, usaremos a estrutura de interface-implementação. Primeiramente, vamos escrever uma interface que vai definir os métodos a serem implementados pelas classes herdeiras.

Mas primeiro, precisamos criar o próprio modelo de tarefa. Vamos criar uma classe Task:

main.java

main.java

copy
12345
public class Task { private int id; private String name; private String description; }

A classe Task contém 3 atributos: id, name e description. Cada tarefa deve ter um nome e descrição, e o id é um atributo necessário para qualquer estrutura de dados. Como mais nós acessaríamos os elementos? Os atributos também são protegidos por o modificador de acesso private, pois não queremos que outras classes tenham acesso direto aos campos desta classe, exceto através do construtor ou getters.

Agora, vamos implementar esses getters e o construtor. Isso pode ser facilmente feito usando a combinação das teclas control + return em um MacBook.

Após as operações realizadas, temos a seguinte classe Task:

Task.java

Task.java

copy
12345678910111213141516171819202122232425262728293031323334
package codefinity.taskManager; public class Task { private int id; private String name; private String description; public Task(int id, String name, String description) { this.id = id; this.name = name; this.description = description; } public int getId() { return id; } public String getName() { return name; } public String getDescription() { return description; } @Override public String toString() { return "Task{" + "id=" + id + ", name='" + name + '\'' + ", description='" + description + '\'' + '}'; } }

Serviços

Teremos um serviço de quadro de tarefas muito simplificado, por isso vamos implementar um serviço que irá adicionar, marcar como concluídas, e verificar se há tarefas na fila. Vamos chamar essa classe de TaskQueueService. Para começar, precisamos definir uma interface com essas tarefas:

TaskQueueService.TaskQueueService

TaskQueueService.TaskQueueService

copy
123456789
package codefinity.taskManager; public interface TaskQueueService { void addTask(Task task); Task getNextTask(); boolean isEmpty(); }

Esta interface define 3 métodos que as classes de implementação devem implementar. Esses métodos incluem adicionar uma tarefa, passar para a próxima tarefa (o que implica que o usuário já completou a tarefa anterior), e um método para verificar se existem tarefas na fila.

Ótimo, vamos agora criar uma classe de implementação que irá sobrescrever e implementar todos esses métodos:

TaskQueueServiceImpl.TaskQueueServiceImpl

TaskQueueServiceImpl.TaskQueueServiceImpl

copy
12345678910
package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.Task; import java.util.LinkedList; import java.util.Queue; public class TaskQueueServiceImpl { private Queue<Task> taskQueue = new LinkedList<>(); }

Criamos um atributo private que será utilizado apenas nesta classe de serviço.

Vale a pena fazer uma pequena digressão e falar sobre classes de serviço, que são uma parte distinta da POO. Classes de serviço são criadas para realizar operações específicas. Elas herdam de interfaces de serviço e implementam seus métodos. Essa abordagem para escrever uma aplicação ajuda a manter e estender a mesma, seguindo os princípios SOLID, os quais estudaremos em um curso separado. No momento, é importante entender que tais classes são criadas exclusivamente para realizar operações em outros objetos.

Por exemplo: Se escrevermos uma calculadora, teremos uma classe separada que armazenará o valor do número em que operamos. As operações de fato serão realizadas usando uma classe de serviço onde adição, subtração e assim por diante são definidos.

Espero que isso esclareça a função das classes de serviço na resolução da tarefa em questão.

Implementação do Serviço

Vamos continuar a execução da tarefa. O próximo passo é demonstrar que essa classe implementa a interface TaskQueueService. Para isso, utilizamos a palavra-chave implements e especificamos a interface que a classe implementa. Também precisamos sobrescrever os métodos definidos pela interface. O IntelliJ IDEA ainda nos permite simplificar significativamente essa tarefa utilizando a combinação option + return.

Agora, em nossa classe, todos os métodos que precisam ser sobrescritos são mostrados. Vamos em frente e façamos isso!

TaskQueueServiceImpl.java

TaskQueueServiceImpl.java

copy
1234567891011121314151617181920212223242526
package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.Task; import codefinity.taskManager.TaskQueueService; import java.util.LinkedList; import java.util.Queue; public class TaskQueueServiceImpl implements TaskQueueService { private Queue<Task> taskQueue = new LinkedList<>(); @Override public void addTask(Task task) { taskQueue.offer(task); } @Override public Task getNextTask() { return taskQueue.poll(); } @Override public boolean isEmpty() { return taskQueue.isEmpty(); } }

No nosso caso, nada excessivamente complicado foi feito. Simplesmente utilizamos os métodos da classe Queue para implementar nossos métodos corretamente. Assim, uma estrutura de dados como a fila facilita a vida de todos os programadores Java.

Usamos o método offer() para adicionar, o método poll() para remover e o método isEmpty() para verificar se a fila está vazia.

Agora é a sua vez de desempenhar um papel na resolução deste problema. Você precisará implementar uma classe de serviço, cuja interface criaremos juntos:

main.java

main.java

copy
12345
package codefinity.taskManager; public interface TaskProcessorService { void processTasks(); }

Criamos uma interface de serviço com um método: processTasks(), que, quando invocado, deve começar a executar todas as tarefas até que a lista de tarefas esteja vazia. Esse método representa um usuário começando a realizar tarefas.

Nota

Se você quiser tornar a tarefa um pouco mais desafiadora, você pode adicionar um método para processar uma única tarefa. Nesse caso, você precisa criar um método separado, processTask(), nesta interface. Este método deve processar a primeira tarefa da lista.

Tarefa

Sua tarefa é escrever uma classe TaskProcessorServiceImpl que deve implementar a interface TaskProcessorService. Esta classe deve ter um método para processar todas as tarefas, o que significa que deve usar métodos do serviço TaskQueueService. Você pode usar composição criando uma instância desta classe dentro da classe que você precisa implementar, por exemplo:

main.java

main.java

copy
1234567
package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.TaskQueueService; public class TaskProcessorServiceImpl { TaskQueueService taskQueueService = new TaskQueueServiceImpl(); }

Em geral, já existe uma composição preparada no topo para sua tarefa. Em seguida, você só precisa implementar um método usando uma instância desta classe.

Depois disso, você precisa criar um construtor que inicializará este objeto da classe taskQueueService.

Deste modo, você poderá usar os métodos deste objeto. Também é evidente que, para o processamento de tarefas, você precisa passar a fila com a qual o taskProcessor vai trabalhar.

O restante da tarefa fica por sua conta. Dicas serão fornecidas no arquivo README.md. Uma vez que sua solução estiver pronta, clique no botão "Executar Testes", e os testes unitários que escrevi verificarão sua solução.

Tudo estava claro?

Como podemos melhorá-lo?

Obrigado pelo seu feedback!

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