• 🎬 Local Record Classes

    (with a “French actors” theme 🇫🇷🎬)

    A local record class is like a local class, except it’s a record declared inside a method body.

    Why it’s useful:
    In stream pipelines you often need a small, temporary “carrier” type for intermediate results (e.g., actor + total earnings). A local record keeps the code readable and strongly typed, without introducing extra top-level classes.

    Example: Top actors by earnings for a given month

    We model:

    • an actor (Actor)
    • a payment for a shooting date (Pay)
    • and inside findTopActors(...) we declare a local record ActorIncome to make stream operations clearer.
    import java.util.*;
    import java.util.stream.*;
    
    record Actor(String name) {}
    
    record Earnings(Actor actor, int year, double amountEur) {}
    
    public class TopPaidActors2009 {
    
        List<Actor> findTopPaidActorsByYear(List<Earnings> earnings, int year) {
    
            // ✅ Local record class (declared inside the method)
            record ActorTotal(Actor actor, double totalEur) {}
    
            return earnings.stream()
                    .filter(e -> e.year() == year)
                    .collect(Collectors.groupingBy(
                            Earnings::actor,
                            Collectors.summingDouble(Earnings::amountEur)
                    ))
                    .entrySet().stream()
                    .map(e -> new ActorTotal(e.getKey(), e.getValue()))
                    .sorted((a, b) -> Double.compare(b.totalEur(), a.totalEur()))
                    .map(ActorTotal::actor)
                    .collect(Collectors.toList());
        }
    
        public static void main(String[] args) {
            Actor dujardin = new Actor("Jean Dujardin");
            Actor boon     = new Actor("Dany Boon");
            Actor marceau  = new Actor("Sophie Marceau");
            Actor merad    = new Actor("Kad Merad");
            Actor canet    = new Actor("Guillaume Canet");
    
            List<Earnings> earnings2009 = List.of(
                    new Earnings(dujardin, 2009, 4_400_000),
                    new Earnings(boon,     2009, 3_000_000),
                    new Earnings(marceau,  2009, 2_900_000),
                    new Earnings(merad,    2009, 2_750_000),
                    new Earnings(canet,    2009, 2_400_000)
            );
    
            TopPaidActors2009 app = new TopPaidActors2009();
            List<Actor> top = app.findTopPaidActorsByYear(earnings2009, 2009);
    
            System.out.println("Top paid French actors (2009):");
            top.forEach(a -> System.out.println(" - " + a.name()));
        }
    }

    Key point: local records are implicitly static

    Just like nested records, a local record is implicitly static.

    That means:

    • methods inside the local record cannot capture variables from the enclosing method,
    • unlike regular local classes (non-record), which can capture effectively final local variables.

    In short: local records are great for clean, temporary data holders—but they don’t close over method locals.