Prática: Aplicações de Coleções

Esta lição é a prática hands-on da Fase 4, consolidando conhecimentos de coleções através de um sistema de gerenciamento de notas.

Requisitos do Projeto

Implementar um sistema de gerenciamento de notas que suporte:

Modelo de Dados

JAVA
import java.util.ArrayList;
import java.util.List;

public class Student {
    private String id;
    private String name;
    private List<Subject> subjects;
    
    public Student(String id, String name) {
        this.id = id;
        this.name = name;
        this.subjects = new ArrayList<>();
    }
    
    public String getId() { return id; }
    public String getName() { return name; }
    public List<Subject> getSubjects() { return subjects; }
    
    public void addSubject(String name, int score) {
        subjects.add(new Subject(name, score));
    }
    
    public double getAverage() {
        if (subjects.isEmpty()) return 0;
        return subjects.stream()
            .mapToInt(Subject::getScore)
            .average()
            .orElse(0);
    }
    
    public int getTotal() {
        return subjects.stream()
            .mapToInt(Subject::getScore)
            .sum();
    }
    
    @Override
    public String toString() {
        return name + " (ID:" + id + ", Média:" + String.format("%.1f", getAverage()) + ")";
    }
}

public class Subject {
    private String name;
    private int score;
    
    public Subject(String name, int score) {
        this.name = name;
        this.score = score;
    }
    
    public String getName() { return name; }
    public int getScore() { return score; }
    
    @Override
    public String toString() {
        return name + ":" + score;
    }
}

Classe Gerenciadora

JAVA
import java.util.*;
import java.util.stream.Collectors;

public class GradeManager {
    private Map<String, Student> students;
    
    public GradeManager() {
        this.students = new LinkedHashMap<>();
    }
    
    // Adicionar estudante
    public void addStudent(Student student) {
        students.put(student.getId(), student);
        System.out.println("Estudante adicionado: " + student.getName());
    }
    
    // Adicionar nota
    public void addScore(String studentId, String subject, int score) {
        Student student = students.get(studentId);
        if (student != null) {
            student.addSubject(subject, score);
            System.out.println(student.getName() + " " + subject + " " + score);
        } else {
            System.out.println("Estudante não encontrado: " + studentId);
        }
    }
    
    // Encontrar estudante
    public Student findStudent(String id) {
        return students.get(id);
    }
    
    // Ordenar por média
    public List<Student> sortByAverage() {
        return students.values().stream()
            .sorted((a, b) -> Double.compare(b.getAverage(), a.getAverage()))
            .collect(Collectors.toList());
    }
    
    // Ordenar por total
    public List<Student> sortByTotal() {
        return students.values().stream()
            .sorted((a, b) -> Integer.compare(b.getTotal(), a.getTotal()))
            .collect(Collectors.toList());
    }
    
    // Calcular pontuação média
    public double getAverageScore() {
        return students.values().stream()
            .mapToDouble(Student::getAverage)
            .average()
            .orElse(0);
    }
    
    // Obter melhor estudante
    public Student getTopStudent() {
        return students.values().stream()
            .max(Comparator.comparingDouble(Student::getAverage))
            .orElse(null);
    }
    
    // Obter pior estudante
    public Student getBottomStudent() {
        return students.values().stream()
            .min(Comparator.comparingDouble(Student::getAverage))
            .orElse(null);
    }
    
    // Agrupar por nota
    public Map<String, List<Student>> groupByGrade() {
        return students.values().stream()
            .collect(Collectors.groupingBy(student -> {
                double avg = student.getAverage();
                if (avg >= 90) return "Excelente";
                if (avg >= 80) return "Bom";
                if (avg >= 70) return "Médio";
                if (avg >= 60) return "Aprovado";
                return "Reprovado";
            }));
    }
    
    // Obter todos os estudantes
    public List<Student> getAllStudents() {
        return new ArrayList<>(students.values());
    }
}

Programa Principal

JAVA
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class GradeSystem {
    private static GradeManager manager = new GradeManager();
    private static Scanner scanner = new Scanner(System.in);
    
    public static void main(String[] args) {
        // Inicializar dados
        initData();
        
        // Loop principal
        int choice;
        do {
            showMenu();
            choice = scanner.nextInt();
            scanner.nextLine();
            
            switch (choice) {
                case 1: listStudents(); break;
                case 2: addScore(); break;
                case 3: viewStudent(); break;
                case 4: showRanking(); break;
                case 5: showStatistics(); break;
                case 6: showGroups(); break;
                case 0: System.out.println("Adeus!"); break;
                default: System.out.println("Escolha inválida");
            }
        } while (choice != 0);
        
        scanner.close();
    }
    
    private static void initData() {
        Student s1 = new Student("S001", "Alice");
        s1.addSubject("Java", 95);
        s1.addSubject("Python", 88);
        s1.addSubject("Banco de Dados", 92);
        
        Student s2 = new Student("S002", "Bob");
        s2.addSubject("Java", 85);
        s2.addSubject("Python", 90);
        s2.addSubject("Banco de Dados", 78);
        
        Student s3 = new Student("S003", "Charlie");
        s3.addSubject("Java", 78);
        s3.addSubject("Python", 82);
        s3.addSubject("Banco de Dados", 88);
        
        manager.addStudent(s1);
        manager.addStudent(s2);
        manager.addStudent(s3);
    }
    
    private static void showMenu() {
        System.out.println("\n=== Sistema de Gerenciamento de Notas ===");
        System.out.println("1. Ver todos os estudantes");
        System.out.println("2. Adicionar nota");
        System.out.println("3. Ver detalhes do estudante");
        System.out.println("4. Ranking de notas");
        System.out.println("5. Estatísticas");
        System.out.println("6. Grupos de notas");
        System.out.println("0. Sair");
        System.out.print("Digite sua escolha: ");
    }
    
    private static void listStudents() {
        System.out.println("\n--- Lista de Estudantes ---");
        for (Student s : manager.getAllStudents()) {
            System.out.println(s);
        }
    }
    
    private static void addScore() {
        System.out.print("Digite o ID do estudante: ");
        String id = scanner.nextLine();
        System.out.print("Digite a disciplina: ");
        String subject = scanner.nextLine();
        System.out.print("Digite a nota: ");
        int score = scanner.nextInt();
        scanner.nextLine();
        
        manager.addScore(id, subject, score);
    }
    
    private static void viewStudent() {
        System.out.print("Digite o ID do estudante: ");
        String id = scanner.nextLine();
        
        Student student = manager.findStudent(id);
        if (student != null) {
            System.out.println("\n--- Notas de " + student.getName() + " ---");
            for (Subject s : student.getSubjects()) {
                System.out.println(s);
            }
            System.out.printf("Total: %d, Média: %.1f%n", 
                student.getTotal(), student.getAverage());
        } else {
            System.out.println("Estudante não encontrado");
        }
    }
    
    private static void showRanking() {
        System.out.println("\n--- Ranking de Notas ---");
        List<Student> ranking = manager.sortByAverage();
        for (int i = 0; i < ranking.size(); i++) {
            Student s = ranking.get(i);
            System.out.printf("%d. %s - Média: %.1f%n", 
                i + 1, s.getName(), s.getAverage());
        }
    }
    
    private static void showStatistics() {
        System.out.println("\n=== Estatísticas ===");
        System.out.printf("Média da classe: %.1f%n", manager.getAverageScore());
        
        Student top = manager.getTopStudent();
        if (top != null) {
            System.out.printf("Maior: %s - %.1f%n", top.getName(), top.getAverage());
        }
        
        Student bottom = manager.getBottomStudent();
        if (bottom != null) {
            System.out.printf("Menor: %s - %.1f%n", bottom.getName(), bottom.getAverage());
        }
    }
    
    private static void showGroups() {
        System.out.println("\n=== Grupos de Notas ===");
        Map<String, List<Student>> groups = manager.groupByGrade();
        
        groups.forEach((grade, students) -> {
            System.out.println("\n" + grade + " (" + students.size() + " estudantes):");
            students.forEach(s -> 
                System.out.println("  " + s.getName() + " - " + String.format("%.1f", s.getAverage())));
        });
    }
}

Exemplo de Saída

TEXT
=== Sistema de Gerenciamento de Notas ===
1. Ver todos os estudantes
2. Adicionar nota
3. Ver detalhes do estudante
4. Ranking de notas
5. Estatísticas
6. Grupos de notas
0. Sair
Digite sua escolha: 4

--- Ranking de Notas ---
1. Alice - Média: 91.7
2. Bob - Média: 84.3
3. Charlie - Média: 82.7

Destaques do Design

Aspecto Descrição
Armazenamento Map Map indexa estudantes por ID
Armazenamento List List armazena notas das disciplinas
Operações Stream Stream para ordenação, estatísticas, agrupamento
Comparator Regras de ordenação personalizadas
Collectors.groupingBy Agrupamento por nível de nota

Recursos Estendidos

Exportação de Notas

JAVA
public void exportToFile(String filename) {
    try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) {
        writer.println("ID,Nome,Java,Python,Banco de Dados,Total,Média");
        for (Student s : students.values()) {
            writer.printf("%s,%s,%s,%d,%.1f%n",
                s.getId(), s.getName(),
                s.getSubjects().stream()
                    .map(sub -> String.valueOf(sub.getScore()))
                    .collect(Collectors.joining(",")),
                s.getTotal(), s.getAverage());
        }
        System.out.println("Exportação bem-sucedida: " + filename);
    } catch (IOException e) {
        System.out.println("Falha na exportação: " + e.getMessage());
    }
}

Estatísticas por Disciplina

JAVA
public Map<String, Double> getSubjectAverages() {
    Map<String, List<Integer>> subjectScores = new HashMap<>();
    
    for (Student student : students.values()) {
        for (Subject subject : student.getSubjects()) {
            subjectScores.computeIfAbsent(subject.getName(), k -> new ArrayList<>())
                .add(subject.getScore());
        }
    }
    
    return subjectScores.entrySet().stream()
        .collect(Collectors.toMap(
            Map.Entry::getKey,
            e -> e.getValue().stream().mapToInt(Integer::intValue).average().orElse(0)
        ));
}

❓ Perguntas Frequentes

P: Como suportar múltiplas turmas? R: Use Map<String, GradeManager> para armazenar múltiplas turmas.

P: Como persistir dados? R: Use IO de arquivo ou armazenamento em banco de dados.

P: Como suportar funcionalidade de importação? R: Leia arquivos CSV e crie objetos Student após análise.

📖 Resumo

📝 Exercícios

  1. Importação: Importe notas de estudantes de um arquivo CSV
  2. Estatísticas por disciplina: Calcule média, máximo, mínimo para cada disciplina
  3. Busca de notas: Suporte busca fuzzy por nome do estudante

Próxima Lição

Na próxima lição, passaremos para a Fase 5 e aprenderemos sobre File IO — operações com arquivos.

100%