Design a logger system that receive stream of messages along with its timestamps, each message should be printed if and only if it isnot printed in the last 10 seconds.
Given a message and a timestamp (in seconds granularity), return true if the message should be printed in the given timestamp, otherwise returns false.
It is possible that several messages arrive roughly at the same time.
Example:
Logger logger = new Logger();
// logging string "foo" at timestamp 1
logger.shouldPrintMessage(1, "foo"); returns true;
// logging string "bar" at timestamp 2
logger.shouldPrintMessage(2,"bar"); returns true;
// logging string "foo" at timestamp 3
logger.shouldPrintMessage(3,"foo"); returns false;
// logging string "bar" at timestamp 8
logger.shouldPrintMessage(8,"bar"); returns false;
// logging string "foo" at timestamp 10
logger.shouldPrintMessage(10,"foo"); returns false;
// logging string "foo" at timestamp 11
logger.shouldPrintMessage(11,"foo"); returns true;
Analysis
Naive implementation would be using hashmap, with key of log message and value of timestamp.
It would pass the OJ, however, there are concerns on the capacity, thinking of it as a cache, then certain eviction policy needed to remove obsolete record to avoid exploding the data structure in memory.
简单地用HashMap可以实现功能,但并不完美,没有考虑到大数据且很多message不同的情形,这样HashMap很有可能造成内存过载。归根结底,这是一个微型系统设计 - design a logger system,因此也考验系统扩展性和健壮性。
This mechanism ensures that the order of iteration of elements is the order in which the elements were lastaccessed, from least-recently accessed to most-recently accessed. The order of elements in the key set is transformed as we perform access operations on the map.
Naive Implementation Using HashMap (not considering capacity) - (134 ms)
classLogger {Map<String,Integer> logs; /** Initialize your data structure here. */publicLogger() {this.logs=newHashMap<>(); } /** Returns true if the message should be printed in the given timestamp, otherwise returns false. If this method returns false, the message will not be printed. The timestamp is in seconds granularity. */publicbooleanshouldPrintMessage(int timestamp,String message) {if (logs.containsKey(message)) {if (timestamp -logs.get(message) >=10) {logs.put(message, timestamp);returntrue; } else {returnfalse; } } else {logs.put(message, timestamp); }returntrue; }}
publicclassLogger {publicMap<String,Integer> map;int lastSecond =0; /** Initialize your data structure here. */publicLogger() { map =newjava.util.LinkedHashMap<String,Integer>(100,0.6f,true) {protectedbooleanremoveEldestEntry(Map.Entry<String,Integer> eldest) {return lastSecond -eldest.getValue() >10; } }; } /** Returns true if the message should be printed in the given timestamp, otherwise returns false. If this method returns false, the message will not be printed. The timestamp is in seconds granularity. */publicbooleanshouldPrintMessage(int timestamp,String message) { lastSecond = timestamp;if(!map.containsKey(message)||timestamp -map.get(message) >=10){map.put(message,timestamp);returntrue; }returnfalse; }}
classLogger {// Algo thinking Queue// time = O(N)classTimeMsg {int timestamp;String msg;publicTimeMsg(int timestamp,String msg) {this.timestamp= timestamp;this.msg= msg; } } /** Initialize your data structure here. */privatestaticfinalint MAX_TIME_WINDOW =10;Queue<TimeMsg> msgQueue;publicLogger() { msgQueue =newLinkedList<>(); } /** Returns true if the message should be printed in the given timestamp, otherwise returns false. If this method returns false, the message will not be printed. The timestamp is in seconds granularity. */publicbooleanshouldPrintMessage(int timestamp,String message) {while (!msgQueue.isEmpty() && timestamp -msgQueue.peek().timestamp>= MAX_TIME_WINDOW) {msgQueue.poll(); }Iterator<TimeMsg> iter =msgQueue.iterator();while (iter.hasNext()) {TimeMsg tm =iter.next();if (tm.msg.equals(message)) returnfalse; }msgQueue.offer(newTimeMsg(timestamp, message));returntrue; }}