描述: 设计一个定时器管理系统,可以动态启动、停止定时器,并能根据已逝去的时长自动调整剩余的时长以及停止定时器
运行时间限制: 1 Sec
内存限制: 无限制
启动定时器:starttimer:ID,time
举例: starttimer:1,1000
启动一个定时器,其ID为1,定时时长time为1000ms
注:定时器ID用例保证非负整数;定时时长一定为正整数停止定时器:stoptimer:ID
举例:
stoptimer:1
停止一个ID为1的定时器
注:定时器ID用例保证非负整数;如果停止的定时器ID不存在,则忽略逝去时长:elapse:time
举例:
elapse:1000
时间逝去1000ms
注:用例保证时长一定为正整数输入结束end
- 输出:
按启动顺序输出还没有停止的定时器,如下ID为1的定时器还有1000ms才结束
timer:1,1000
如果所有定时器都停止了,输出none
样例输入:
starttimer:1,1000
starttimer:2,2000
elapse:1000
end
样例输出:
timer:2,1000
这道题最终并没有AC,仔细阅读了所有要求,提取得到的关键信息有:
- 输入有四种,分别对应处理;
- 输入为stoptimer时,注意定时器不存在的情况;
输入结束时,要按照启动顺序来依次输出没有停止的定时器,没有时输出none;
其中的第三点很容易遗漏,这里要注意HashMap、TreeMap、LinkedListMap、HashTable四者的使用区别:
Map用于存储键值对,根据键得到值,因此不允许键重复,值可以重复。以上四种都是Java为数据结构中的映射定义了一个接口java.util.Map的四个实现类。
- HashMap是一个最常用的Map,它根据键的hashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap**最多只允许一条记录的键为null**,不允许多条记录的值为null。HashMap**不支持线程的同步**,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致。如果需要同步,可以用Collections.synchronizedMap(HashMap map)方法使HashMap具有同步的能力。
- Hashtable与HashMap类似,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,然而,这也导致了Hashtable在写入时会比较慢。
- LinkedHashMap**保存了记录的插入顺序,在用Iteraor遍历LinkedHashMap时,先得到的记录肯定是先插入的。在遍历的时候会比HashMap慢**。有HashMap的全部特性。
- TreeMap能够把它保存的记录根据键排序,默认是按升序排序,也可以指定排序的比较器。当用Iteraor遍历TreeMap时,得到的记录是排过序的。TreeMap的键和值都不能为空。
迭代时注意map的遍历方法及遍历时报错:
map的遍历方法
//第一种:普遍使用,二次取值
System.out.println("通过Map.keySet遍历key和value:");
for (String key : map.keySet()) {
System.out.println("key= "+ key + " and value= " + map.get(key));
}
//第二种
System.out.println("通过Map.entrySet使用iterator遍历key和value:");
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
//第三种:推荐,尤其是容量大时
System.out.println("通过Map.entrySet遍历key和value");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
//第四种
System.out.println("通过Map.values()遍历所有的value,但不能遍历key");
for (String v : map.values()) {
System.out.println("value= " + v);
}
在使用iterator.hasNext()操作迭代器的时候,如果此时迭代的对象发生改变,比如插入了新数据,或者有数据被删除。
则使用会报以下异常:
Java.util.ConcurrentModificationException
at java.util.HashMap\$HashIterator.nextEntry(HashMap.java:793)
at java.util.HashMap\$KeyIterator.next(HashMap.java:828)
解决办法:java.util.ConcurrentModificationException 解决办法
3. 其他OJ的一些编程建议:if else括号,map遍历在entrySet上使用iterator比keySet再Map.get更高效....
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
Map<String,Integer> map= new LinkedHashMap<String,Integer>();
while(sc.hasNext()){
String str=sc.nextLine();
if(str.equals("end")) break;
String[] temp=str.split(":");
if(temp[0].equals("starttimer")){
String[] info=temp[1].split(",");
String id=info[0];
int time=Integer.parseInt(info[1]);
map.put(id, time);
}
else if(temp[0].equals("elapse")){
int time=Integer.parseInt(temp[1]);
if(time>0){
Iterator<Map.Entry<String,Integer>> it= map.entrySet().iterator();
while(it.hasNext()){
Map.Entry<String, Integer> entry = it.next();
String key=entry.getKey();
int left=entry.getValue()-time;
if(left<=0){
it.remove();
}
else{
map.remove(key);
map.put(key, left);
}
}
}
}
else if(temp[0].equals("stoptimer")){
if(map.containsKey(temp[1])){
map.remove(temp[1]);
}
}
}
int len=map.size();
if(len==0){
System.out.println("none");
}
else{
for(Map.Entry<String, Integer> entry : map.entrySet()){
System.out.println("timer:"+entry.getKey()+","+entry.getValue());
}
}
}
}