您的位置:首页 > 产品设计 > UI/UE

面试中关于key/value的问题及map的理解

2016-08-04 19:09 393 查看
面试问题1  用什么数据结构来存放电视剧,并且输出为有序。面试问题2 统计一个字符串中单词的频率,并且频率按从大到小的顺序排列对于第一个问题:把包含电视剧名字和集数的字符串作为key,对应的存储位置做为value 。用treemap比较合适。对于第二个问题:单词作为key,出现的次数作为value。由于treemap的默认排序是对key进行排序,用treemap不合适,不如直接用hashmap,存取效率高。排序单独设计。基础知识:先来理解一下mapmap有两种理解方式,一种是当成key/value来理解,可以存放包含key/value属性的对象;另一种更理解可以理解为一种特殊的数组,只不过这个数组的下标【index】可以是任意对象。hashmap在存储键值对时借助了“数组+链表”的方式,就是哈希表。存取元素:HashMap 在底层将 key-value 当成一个整体进行处理,这个整体就是一个 Entry 对象。HashMap 底层采用一个 Entry[] 数组来保存所有的 key-value 对,当需要存储一个 Entry 对象时,会根据hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,也会根据hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Entry。我们对一个键值对的查询,是分为四步的。先根据key值计算出hash值以及h值(h值是java实现中处理得到的更优的index索引值)查找table数组中的h位置,得到相应的键值对链表根据key值,遍历键值对链表,找到相应的键值对,从键值对中取出value值。hashmap()查找,插入,删除的时间复杂度可以认为为O(1);LinkedHashMap物理结构和hashmap差不多,只不过hashmap中,hashtable里存储的元素为链表的header,而在LinkedHashMap里面,hashTable里存储的元素为双向链表结点,结点的数据元素为header,结点的next或previous指向其他hashTable位置结点,从而可以实现按照插入或者访问顺序存储。LinkedHashMap的双向链表为循环双向链表。为什么要用循环双向链表而不是普通双向链表,我个人认为这样可以少记一个头节点或者尾结点的位置。迭代器要想正向或逆向打印双链表,只需要知道header位置即可。(循环双向链表的头部存放的是最久访问的节点或最先插入的节点,尾部为最近访问的或最近插入的节点,迭代器遍历方向是从链表的头部开始到链表尾部结束,在链表尾部有一个空的header节点,该节点不存放key-value内容,为LinkedHashMap类的成员属性,循环双向链表的入口。这句话其实就是描述了一个循环双向链表的结构,尾部都会空一个,作为header。)迭代器总的过程应该是这样的:LinkedHashMap只有一个入口,就是数组hashtable的头地址。迭代器通过HashTable的头结点next或previou,找到循环双线链表头节点或尾节点,从而可以正向或逆向打印元素。LinkedHashmap()查找,插入,删除的时间复杂度也为O(1),但却实现了可以按照key的插入顺序或访问顺序输出元素。treemap的存储结构用的是红黑树。红黑树的操作时间跟二叉查找树的时间复杂度是一样的,执行查找、插入、删除等操作的时间复杂度为O(logn)。面试问题1的实现import java.util.*;public class TestTreeMapDelete {public static void main(String[] args) {TreeMap<String, Integer> treemap = new TreeMap<String, Integer>();treemap.put("fengshen_001", 342314);treemap.put("fengshen_004", 322514);treemap.put("fengshen_005", 341319);treemap.put("fengshen_002", 344364);treemap.put("fengshen_004", 322514);System.out.println(treemap);System.out.println(treemap.subMap("fengshen_002", "fengshen_004"));}}
面试问题2的实现:
<pre name="code" class="java">import java.util.*;public class CountOccurenceOfWordsAdv {public static void main(String[] args) {// Text in a stringString text = "Have a good day. Have a good class. " +"Have a good visit. Have fun!";// Create a hash map to hold words and key and count as valueHashMap<String, Integer> hashMap = new HashMap<String, Integer>();StringTokenizer st = new StringTokenizer(text, " .!?");while (st.hasMoreTokens()) {String key = st.nextToken();if (hashMap.get(key) != null) {int value = ((Integer)hashMap.get(key)).intValue();value++;hashMap.put(key, new Integer(value));}else {hashMap.put(key, new Integer(1));}}// Get an entry set for the tree mapSet<Map.Entry<String, Integer>> entrySet = hashMap.entrySet();// Get an iterator for the entry setIterator<Map.Entry<String, Integer>> iterator = entrySet.iterator();ArrayList<WordOccurrence> list = new ArrayList<WordOccurrence>();while (iterator.hasNext()) {StringTokenizer st1 =new StringTokenizer(iterator.next().toString(), "=");list.add(new WordOccurrence(st1.nextToken(),Integer.parseInt(st1.nextToken())));}Collections.sort(list);for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i));}}}class WordOccurrence implements Comparable {String word;int count;public WordOccurrence(String word, int count) {this.word = word;this.count = count;}public int compareTo(Object o) {//	    return count - ((WordOccurrence)o).count;return ((WordOccurrence)o).count - count;}public boolean equals(Object o) {return word.equals(((WordOccurrence)o).word);}public String toString() {return word + " " + count;}}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: