剑指Offer-51——字符流中第一个不重复的字符与本题中HashMap和LinkedHashMap的区别
程序员文章站
2022-03-14 20:45:03
...
题目描述
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
输出描述:
如果当前字符流没有存在出现一次的字符,返回#字符。
思路解析
这里使用的是LinkedHashMap
来解决。输入进来就判断是否map中含有,不含有就放入并设置值为1,。含有,则取出value值并将其加1后放入。
代码
import java.util.Map;
import java.util.LinkedHashMap;
public class Solution {
Map<Character,Integer> map = new LinkedHashMap<>();
//Insert one char from stringstream
public void Insert(char ch)
{
if(!map.containsKey(ch)){
map.put(ch,1);
}else{
map.put(ch,map.get(ch)+1);
}
}
//return the first appearence once char in current stringstream
public char FirstAppearingOnce()
{
//如果大小为0就返回‘#’
if(map.size() == 0) return '#';
for(char c : map.keySet()){
if(map.get(c)==1){
return c;
}
}
return '#';
}
}
看看HashMap和LinkedHashMap的区别
- 看看HashMap的存储的形式:
从这里我们可以看到HashMap的底层数据结构是数组(Entry)+链表(才有头插法,长度超过8转换为红黑树)。
- LinkedHashMap是HashMap的子类,但是内部还有一个双向链表维护键值对的顺序,每个键值对既位于哈希表中,也位于双向链表中。LinkedHashMap支持两种顺序插入顺序 、 访问顺序
1.插入顺序:先添加的在前面,后添加的在后面。修改操作不影响顺序
2.访问顺序:所谓访问指的是get/put操作,对一个键执行get/put操作后,其对应的键值对会移动到链表末尾,所以最末尾的是最近访问的,最开始的是最久没有被访问的,这就是访问顺序。
- 为什么这里用LinkedHashMap而不是HashMap ?
首先:HashMap是一个散列表。存储的时候是依据hashcode来进行存储的,因而遍历时,取得数据的顺序是完全随机的。
LinkedHashMap保存了记录的插入顺序,在用遍历LinkedHashMap时,先得到的记录肯定是先插入的。也可以在构造时带参数,按照应用次数排序。这里我们有一个先后顺序的关系,先为第一个出现一次的先出去
。这就是只用LinkedHashMap而不是HashMap的原因(这里也可以考虑使用队列来做一个记录)
其次:在遍历的时候会比HashMap慢,不过有种情况例外:当HashMap容量很大,实际数据较少时,遍历起来可能会比LinkedHashMap慢。因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。这里会频繁的访问进入的和出去的字符流,因此前几个数据不会很大。