Start learning free

LESSON 555 OF 569 · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

Ticket Numbers in Java: Static Members and a Shared Counter

Practice O(1) Read the full explanation

A ticket machine gives every new ticket the next number: the first ticket gets 1, the next one 2, and so on. The counter belongs to the class, not to any one ticket: it is a static member of Ticket, one copy shared by all the tickets. Each ticket keeps its own number, copied from the counter when the ticket is created.

Implement the class Ticket:

  • Ticket(name) creates a ticket for name. It adds 1 to the class-level counter and gives the new ticket that value as its number. The ticket keeps its name and its number in two fields, name and number.
  • The static method issued() returns how many tickets were created since the counter was last reset.
  • The static method resetCounter() sets the counter back to 0, so the next ticket gets number 1 again.

For each test case, the test code calls resetCounter() through the class name, then creates one ticket per name, in order. Once all the tickets of the case exist, it prints each ticket as its name, a space, # and its number, one ticket per line, and then the value of issued() on a line of its own.

The starter code spells these names the way your language does: reset_counter in Python, Issued and ResetCounter in C#. In Python the counter is a class attribute and the two methods are marked @staticmethod; in Kotlin and Scala the counter and the two methods live in the companion object, as in the Static Members lesson.

 

Example 1:

Input:
    Ticket("Ann")
    Ticket("Bob")
    Ticket("Cy")
Output:
Ann #1
Bob #2
Cy #3
3
Explanation: resetCounter() set the counter to 0. Each new ticket adds 1 to it and keeps the new value,
so the tickets get 1, 2 and 3, and issued() returns 3.

Example 2:

Input:
    Ticket("Mia")
    Ticket("Mia")
Output:
Mia #1
Mia #2
2
Explanation: The number comes from the shared counter, not from the name, so the two tickets for Mia
get different numbers. The numbers start at 1 again because resetCounter() ran before this case.

Example 3:

Input:
    (no tickets)
Output:
0
Explanation: resetCounter() set the counter to 0 and no ticket was created, so issued() returns 0.

 

Constraints:

  • A test case creates from 0 to 1000 tickets.
  • A name is one word of 1 to 20 English letters. Two tickets can have the same name.
  • The tickets are printed only after all of them were created, so every ticket must store its own number: reading the shared counter when printing would give every ticket the last number.
STEP 1 OF 7
    Ctrl + Enter to check

    JAVA · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

    Ticket Numbers in Java, explained

    Problem overview

    A ticket machine gives every new ticket the next number: 1, then 2, and so on. The class Ticket does the same. Each ticket keeps its own name and number, but the counter that hands out the numbers belongs to the class itself, not to any single ticket. In Java that is a static member: one copy, shared by every ticket.

    The class has three parts:

    • Ticket(name) adds 1 to the counter and gives the new ticket that value as its number.
    • The static method issued() returns how many tickets were created since the last reset.
    • The static method resetCounter() sets the counter back to 0, so the next ticket gets number 1 again.

    Creating tickets for Ann, Bob and Cy after a reset gives them the numbers 1, 2 and 3, and issued() returns 3. With no tickets created, issued() returns 0. Two tickets for the same name still get different numbers, because the number comes from the counter, not from the name.

    Approach: instance fields and static fields

    Every ordinary field, such as name, exists once per object. A static field exists once per class. That is exactly the split this problem needs: name and number are different for every ticket, while the counter must be one value that all tickets see and change.

    The key detail is that each ticket copies the counter's value into its own number at the moment it is created. The counter keeps moving as more tickets are made, but a ticket's number is its own field and doesn't move with it. If the code printed the shared counter instead of each ticket's own number, every ticket would show the last value.

    Step by step

    1. Declare the counter as public static int count = 0 at the top of the class. The initializer runs once, when the class is loaded.
    2. Declare the per-ticket fields name and number without static, so each ticket has its own.
    3. Store the name in the constructor with this.name = name.
    4. Add 1 to the counter with count++. Every ticket made counts once, whatever its name.
    5. Copy the counter into the ticket's number with this.number = count. The counter has just been increased, so the first ticket after a reset gets 1.
    6. issued returns count.
    7. resetCounter assigns 0 to count.

    The solution in Java

    class Ticket {
        public static int count = 0;
        public String name;
        public int number;
        public Ticket(String name) {
            this.name = name;
            count++;
            this.number = count;
        }
        public static int issued() {
            return count;
        }
        public static void resetCounter() {
            count = 0;
        }
    }
    

    Things worth knowing about static members:

    • You call a static method on the class name: Ticket.issued(), with no ticket needed. For that reason a static method can use only static members. It has no this, because no particular ticket is involved.
    • A constructor and instance methods can use static fields freely. Inside the class you write just count; outside it you write Ticket.count.
    • Java also lets you write someTicket.count, but it still reads the shared field, which is misleading. Prefer the class name.

    Using the class

    Ticket.resetCounter();
    Ticket x = new Ticket("Ann");
    Ticket y = new Ticket("Bob");
    Ticket z = new Ticket("Cy");
    System.out.println(x.name + " #" + x.number);
    System.out.println(y.name + " #" + y.number);
    System.out.println(z.name + " #" + z.number);
    System.out.println(Ticket.issued());
    Ticket.resetCounter();
    System.out.println(Ticket.issued());
    Ticket m = new Ticket("Mia");
    System.out.println(m.number + " " + x.number + " " + Ticket.issued());
    

    prints:

    Ann #1
    Bob #2
    Cy #3
    3
    0
    1 1 1
    

    The last line shows both ideas. After the reset, Mia is ticket 1, and Ann's ticket still has number 1 as well, because a reset changes only the counter, not the tickets already made.

    Why a reset matters

    The counter is static, so it lives as long as the program does, not as long as any one ticket. Creating tickets in a second round without resetting would continue from the last number: after tickets 1, 2 and 3, the next ticket is 4. That is why a fresh round starts with resetCounter(): it sets the one shared value back to 0 and the next ticket is number 1 again. Tickets made before the reset keep their numbers, because those numbers were copied into their own fields.

    Common mistakes

    • Printing the counter instead of the ticket's number. If the tickets are printed after all are created, this version shows the same value for everyone:
      System.out.println(x.name + " #" + Ticket.count);
      System.out.println(y.name + " #" + Ticket.count);
      System.out.println(z.name + " #" + Ticket.count);
      
      It prints Ann #3, Bob #3 and Cy #3. Each ticket must store its own number in the constructor.
    • Making number static. Then there is one number for all tickets, and every ticket would report the latest one.
    • Making count an instance field. Each ticket would start its own counter at 0, so every ticket would get number 1 and issued() would not compile as a static method.
    • Increasing the counter after copying it. If this.number = count runs before count++, numbers start at 0.
    • Using this in a static method. It doesn't compile, because a static method isn't called on any ticket.

    Complexity

    The constructor and both static methods do a constant amount of work, so each is O(1). Each ticket stores two values, a name and a number, and the class stores one counter.

    Keep going with Java500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free