剑指Offer-51——字符流中第一个不重复的字符与本题中HashMap和LinkedHashMap的区别

题目描述

请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"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的遍历速度和他的容量有关。这里会频繁的访问进入的和出去的字符流,因此前几个数据不会很大。

猜你喜欢

转载自blog.csdn.net/H1517043456/article/details/107504778