Java:在最后一分钟实现 Hit() 和 getNumHits()

标签 java algorithm data-structures

这更像是一个设计问题,但我只是想知道是否有人对这个问题有任何想法。

在一次面试中,我被要求设计 2 个方法。

hit();
getNumHits();

hit() 每次用户向服务器发出请求时调用,getNumHits() 返回最后一分钟的点击次数。

有什么想法吗?

更新:

我知道这是一个副本

Implementation of a "hits in last [second/minute/hour]" data structure

但我在理解 C++ 代码时遇到了一些困难,想知道我们是否可以获得 Java 版本的答案!

最佳答案

您要寻找的核心是保留最后一分钟内所有匹配项的列表。使用 LinkedList 可以实现快速的 removeFirst()

class HitCounter {

    // My most recent list - only the last minute is retained.
    LinkedList<Long> hitList = new LinkedList<>();
    private static final long OneMinute = 1000L * 60L;

    public void hit() {
        // Track the hit.
        hitList.add(System.currentTimeMillis());
        // Always clean up.
        cleanup();
    }

    public int hitCount() {
        // Make sure we are clean.
        cleanup();
        return hitList.size();
    }

    private void cleanup() {
        // Eat all stale hits.
        while (hitList.getFirst() < System.currentTimeMillis() - OneMinute) {
            hitList.removeFirst();
        }
    }
}

但是,如果您的命中非常快,并且您怀疑保留所有命中的所有时间是否有效,您可以使用桶系统进行量化。在这里,我每一秒都在计数。很明显,你可能会在一秒钟内被击中多少次。

class HitCounter {

    // One bucket - keeps track of how many hits since the start time.
    private class Bucket {

        // Probably should use an atomic.
        int count;
        // The time this bucket was started.
        long started = System.currentTimeMillis();
    }
    // My most recent list - only the last minute is retained.
    LinkedList<Bucket> hitList = new LinkedList<>();
    private static final long OneSecond = 1000L;
    private static final long OneMinute = OneSecond * 60L;

    public void hit() {
        // Grab the hit time.
        long now = System.currentTimeMillis();
        // Normally goes in the last bucket.
        Bucket bucket = hitList.size() > 0 ? hitList.getLast() : null;
        // Time for new bucket?
        if (bucket == null || now > bucket.started + OneSecond) {
            // Yup!
            hitList.add(bucket = new Bucket());
        }
        // Track the hit.
        bucket.count++;
        // Always clean up.
        cleanup();
    }

    public int hitCount() {
        // Make sure we are clean.
        cleanup();
        // Add up all the bucket counts.
        int total = 0;
        for (Bucket bucket : hitList) {
            total += bucket.count;
        }
        return total;
    }

    private void cleanup() {
        // Eat all stale hits.
        while (hitList.size() > 0 && hitList.getFirst().started < System.currentTimeMillis() - OneMinute - OneSecond) {
            hitList.removeFirst();
        }
    }
}

public void test() throws InterruptedException {
    HitCounter hitList = new HitCounter();
    for (int i = 0; i < 90; i++) {
        hitList.hit();
        System.out.println(i + " - " + hitList.hitCount());
        Thread.sleep(1000);
    }
}

关于Java:在最后一分钟实现 Hit() 和 getNumHits(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35319150/

相关文章:

algorithm - 返回给定时间间隔内插入的项目

c++ - 适合图中不断删除的最佳数据结构

iphone - 用于存储大量记录的应用程序结构

c++ - 在二维数组中查找最大值的快速算法

c++ - OBB(定向边界框)算法中的点?

c - 使用堆栈计算表达式 (C)

java - Selenium(JAVA) 网格仅在 Windows 中同时启动 10 个浏览器

java - 如何确保 INSERT INTO 不会在 mySQL 数据库上添加相同的值

java - 使用小程序时无法获取默认打印机名称 - ZK Framework

java - 为什么重载不支持多态