Vending Machine in Java - Interview Question Asked in Amazon, Google, Adobe

Introduction

In this post, we will create a fully functional vending machine in Java that simulates the purchasing process. The vending machine allows users to select items, insert coins, and dispense selected items if enough money is inserted. It also handles refunds, manages item and coin inventories, and calculates the appropriate change if excess coins are inserted.

This vending machine follows object-oriented principles, making the code reusable and modular.

Vending Machine in Java


Problem Statement

We need to design a vending machine in Java that:

  • Displays a set of items and their prices.
  • Accepts coins and tracks the balance.
  • Dispenses an item if enough coins are inserted.
  • Returns change if more money is inserted than needed.
  • Allows users to request a refund before purchasing an item.
  • Alerts when an item is out of stock or if there isn’t enough money.
  • Tracks item and coin inventories.

Example:

  • Input: Select item TWIX, insert 50 (price: 35)
  • Output: Dispense TWIX, return 15 as change.

Vending Machine Design

Components:

  1. Coin Enum: Represents the different coin denominations.
  2. Item Enum: Represents the items available in the vending machine.
  3. Inventory Class: Manages the stock levels of coins and items.
  4. Selector Interface: Defines the core functions of the vending machine, such as selecting an item, inserting coins, purchasing, and requesting refunds.
  5. VendingMachine Class: Implements the Selector interface, handling the main logic, such as managing coins, items, transactions, and dispensing change.
  6. Main Class: The driver class to demonstrate the functionality of the vending machine.

Vending Machine Implementation in Java

1. Coin Enum

The Coin enum defines the accepted coin denominations: PENNYNICKELDIME, and QUARTER.
public enum Coin {
    PENNY(1), NICKEL(5), DIME(10), QUARTER(25);

    private final int denomination;

    Coin(int denomination) {
        this.denomination = denomination;
    }

    public int getDenomination() {
        return denomination;
    }
}

2. Item Enum

The Item enum defines the available items in the vending machine along with their prices.
public enum Item {
    SKITTLES("Skittles", 15), TWIX("Twix", 35), SNICKERS("Snickers", 25);

    private final String name;
    private final int price;

    Item(String name, int price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public int getPrice() {
        return price;
    }
}

3. Inventory Class

This class manages the inventory of both coins and items, allowing you to add items, deduct from the inventory, and check if an item or coin is in stock.
import java.util.HashMap;
import java.util.Map;

public final class Inventory<T> {
    private Map<T, Integer> inventory = new HashMap<>();

    public int getQuantity(T item) {
        return inventory.getOrDefault(item, 0);
    }

    public void add(T item, int quantity) {
        int count = inventory.getOrDefault(item, 0);
        inventory.put(item, count + quantity);
    }

    public void deduct(T item) {
        if (hasItem(item)) {
            int count = inventory.get(item);
            inventory.put(item, count - 1);
        }
    }

    public boolean hasItem(T item) {
        return getQuantity(item) > 0;
    }

    public void clear() {
        inventory.clear();
    }
}

4. Selector Interface

  • The Selector interface defines the core methods for the vending machine, such as selecting an item, inserting coins, purchasing an item, and requesting a refund.
import java.util.List;
import java.util.Map;

public interface Selector {
    void selectItem(Item item);
    int checkPrice(Item item);
    void insertCoin(Coin coin);
    Map<Item, List<Coin>> purchaseItem();
    List<Coin> refund();
    void reset();
}

5. Vending Machine Class

This class implements the core vending machine logic. It manages item selection, coin insertion, item purchase, refunds, and calculating the change.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

public class VendingMachine implements Selector {
    private Inventory<Coin> coinInventory = new Inventory<>();
    private Inventory<Item> itemInventory = new Inventory<>();
    private int currentBalance;
    private Item currentItem;

    public VendingMachine() {
        initializeMachine();
    }

    // Initialize the vending machine with items and coins
    private void initializeMachine() {
        for (Coin coin : Coin.values()) {
            coinInventory.add(coin, 10); // Adding 10 coins of each type
        }
        for (Item item : Item.values()) {
            itemInventory.add(item, 5); // Adding 5 of each item
        }
    }

    @Override
    public void selectItem(Item item) {
        if (itemInventory.hasItem(item)) {
            currentItem = item;
            System.out.println("Selected item: " + item.getName());
        } else {
            System.out.println("Item is out of stock.");
        }
    }

    @Override
    public int checkPrice(Item item) {
        return item.getPrice();
    }

    @Override
    public void insertCoin(Coin coin) {
        currentBalance += coin.getDenomination();
        coinInventory.add(coin, 1);
        System.out.println("Inserted " + coin + ". Current balance: " + currentBalance);
    }

    @Override
    public Map<Item, List<Coin>> purchaseItem() {
        if (currentItem == null) {
            throw new IllegalStateException("No item selected.");
        }
        if (currentBalance >= currentItem.getPrice()) {
            int changeAmount = currentBalance - currentItem.getPrice();
            List<Coin> change = getChange(changeAmount);
            itemInventory.deduct(currentItem);
            currentBalance = 0;
            System.out.println("Dispensing " + currentItem.getName());
            return Collections.singletonMap(currentItem, change);
        } else {
            throw new IllegalStateException("Insufficient balance.");
        }
    }

    @Override
    public List<Coin> refund() {
        List<Coin> refund = getChange(currentBalance);
        currentBalance = 0;
        return refund;
    }

    @Override
    public void reset() {
        itemInventory.clear();
        coinInventory.clear();
        currentBalance = 0;
        initializeMachine();
    }

    private List<Coin> getChange(int amount) {
        List<Coin> change = new ArrayList<>();
        while (amount > 0) {
            if (amount >= Coin.QUARTER.getDenomination() && coinInventory.hasItem(Coin.QUARTER)) {
                change.add(Coin.QUARTER);
                amount -= Coin.QUARTER.getDenomination();
            } else if (amount >= Coin.DIME.getDenomination() && coinInventory.hasItem(Coin.DIME)) {
                change.add(Coin.DIME);
                amount -= Coin.DIME.getDenomination();
            } else if (amount >= Coin.NICKEL.getDenomination() && coinInventory.hasItem(Coin.NICKEL)) {
                change.add(Coin.NICKEL);
                amount -= Coin.NICKEL.getDenomination();
            } else if (amount >= Coin.PENNY.getDenomination() && coinInventory.hasItem(Coin.PENNY)) {
                change.add(Coin.PENNY);
                amount -= Coin.PENNY.getDenomination();
            } else {
                throw new IllegalStateException("Insufficient change available.");
            }
        }
        return change;
    }
}

6. Main Class

The Main class demonstrates the usage of the vending machine, including selecting an item, inserting coins, purchasing, and refunding.
public class Main {
    public static void main(String[] args) {
        VendingMachine vm = new VendingMachine();

        // Select item TWIX
        vm.selectItem(Item.TWIX);

        // Insert coins
        vm.insertCoin(Coin.QUARTER);  // 25
        vm.insertCoin(Coin.QUARTER);  // 25, total 50

        // Purchase item
        vm.purchaseItem();

        // Example of refund (if no purchase was made)
        List<Coin> refund = vm.refund();
        System.out.println("Refunded coins: " + refund);
    }
}

Output:

Selected item: Twix
Inserted QUARTER. Current balance: 25
Inserted QUARTER. Current balance: 50
Dispensing Twix
Vending Machine in Java Program Example

Conclusion

This complete Java vending machine simulates a real-world vending machine. The code manages coins and items, handles transactions, and ensures that the correct change is returned to the user. The design follows object-oriented principles, making it easy to extend and maintain.

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare