Code · LLD machine coding · Problems

URL Shortener

Design a URL shortener.

1 class 31 lines View on GitHub ↗

Question

Design a URL shortener.

  • getShortURL(longUrl) returns http://short.ly/<code>. The same long URL always gets the same code.
  • expandShortUrl(shortUrl) returns the original URL.
  • Must be safe under concurrent calls.

Design: an AtomicLong counter encoded in base 62 (0-9, a-z, A-Z), with two ConcurrentHashMaps (code ↔ URL). computeIfAbsent makes “same URL → same code” atomic.

URLShortner.java 31 lines GitHub ↗
package lld.urlShortner;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

public class URLShortner {
    private final AtomicLong counter = new AtomicLong(100000);
    private static String BASE = "http://short.ly/";
    private static final String CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final ConcurrentHashMap<String , String> codeToUrl = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<String , String> urltoCode = new ConcurrentHashMap<>();

    public String getShortURL(String longUrl) {
        String code = urltoCode.computeIfAbsent(longUrl , u -> {
            String c = encoder(counter.getAndIncrement());
            codeToUrl.put(c, u);
            return c;
        });
        return BASE + code;
    }

    public static String expandShortUrl(String url) {
        String code = url.substring(BASE.length());
        return codeToUrl.get(code);
    }

    private String encoder(long id) {
        StringBuilder sb = new StringBuilder();
        while(id > 0) {
            sb.append(CHARS.charAt((int)id%62));
            id = id/62;
        }
        return sb.reverse().toString();
    }


}