Inventory Class with Encapsulation

Problem

Write an Inventory class that hides its data and offers three methods: add(name, qty), remove(name, qty) and quantity(name). Every input line is a command: ADD name qty, REMOVE name qty or QUERY name. Print one line per command. ADD prints ok. REMOVE prints ok, or error when there is not enough stock (then nothing changes). QUERY prints the quantity (0 for an unknown item).

Constraints

  • 1 <= lines <= 10^4
  • 0 < qty <= 10^6

Examples

Input

ADD pen 10
REMOVE pen 4
QUERY pen
REMOVE pen 7

Output

ok
ok
6
error

Solutions

Best approachTime O(n)Space O(n)

The class owns its data. The only way to change stock is through add and remove, and remove checks the rule. If the rule changes later, only this class changes.

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Process lines.
 * Input   : Several command lines.
 * Output  : One result per command.
 * Approach: Class with private data.
 * Time    : O(n)
 * Space   : O(n)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
        // Step 1: The map is private. Other code can change stock only through the methods.
        static class Inventory {
            private final java.util.Map<String, Long> stock = new java.util.HashMap<String, Long>();

            void add(String name, long qty) {
                stock.put(name, quantity(name) + qty);
            }

            // Step 2: remove() protects the rule "stock never goes below zero".
            boolean remove(String name, long qty) {
                if (quantity(name) < qty) {
                    return false;
                }
                stock.put(name, quantity(name) - qty);
                return true;
            }

            long quantity(String name) {
                Long value = stock.get(name);
                return value == null ? 0 : value;
            }
        }

    // This method solves the task. It receives the input and returns the answer.
    static String[] solve(String[] lines) {
        Inventory inventory = new Inventory();
        String[] output = new String[lines.length];
        for (int i = 0; i < lines.length; i++) {
            String[] part = lines[i].split(" ");
            if (part[0].equals("ADD")) {
                inventory.add(part[1], Long.parseLong(part[2]));
                output[i] = "ok";
            } else if (part[0].equals("REMOVE")) {
                output[i] = inventory.remove(part[1], Long.parseLong(part[2])) ? "ok" : "error";
            } else {
                output[i] = String.valueOf(inventory.quantity(part[1]));
            }
        }
        return output;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        java.util.List<String> all = new java.util.ArrayList<>();
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();
            if (!line.isEmpty()) {
                all.add(line);
            }
        }
        String[] lines = all.toArray(new String[0]);
        System.out.println(String.join("\n", solve(lines)));
    }
}
Hints (2)
  1. Why is the map private?
  2. Which method must check for enough stock?