1. scala的map存储散列算法是字典顺序吗
不是,那个效率太低了
一、 使用 拉链式存储
这个以 Java 中的 HashMap 为例进行讲解。 HashMap 的内部有个数组 Entry[] table, 这个数组就是存放数据的。
Entry 类的定义大致是 :
class Entry {
Object key
Object value
Entry next;
}
所以, Entry[] table 的每个元素都是一个链表,即 HashMap 的内部存储是 数组 + 链表,即拉链式存储。
当往 HaspMap 中 put(key, value) 数据时,先进行 key.hashCode() & (table.length() - 1) ,得到一个小于 table.length() 的值, 称为 index, 则这个新的 Entry 就属于 table[index] 这个链表了 ( 如果链表还不存在,则把这个新的 Entry 作为链表的头部了 ); 然后开始从前往后遍历 table[index] 这个链表,如果 key.equals( entry.key ), 那么表示这个 key 已经有了旧值,则替换 value 的值即可;
否则,把这个新的 Entry 插入到 table[index] 链表的最前面.
以上就是 HashMap 的存储方式介绍了, 而且可以知道,作为 HashMap 的 Key, 它的 hashCode() 和 equals() 方法都被使用了
二、数组存储
1.分散的数组存储
这个以 ThreadLocal 和 ThreadLocal.Values 类为例进行讲解。 Values 类里面有两个变量, Object[] table, 和 mask , table 就是存储数据的数组了,table 的长度是 2 的倍数 , mask 的值就是 table.length - 1 ; 这一点和 HashMap 的内部存储很像。 不过 table 中的每个元素就不是链表了。
当往 Values 中进行 put(key, value) 时,先进行 key.hashCode & mask ,得到一个小于 table.length 的值,称为 index (与上面的 HashMap 好像,哈哈), 然后去检查 table[index] 的值,如果不存在,则在 table[index] 处放入 key, table[index + 1] 处放入 value; 如果已经存在了,且 key.equals( oldKey ) 不成立,即发生了冲突,那么 index = index + 2 ( 此处是 + 2,因为 key ,value 两个是挨着放的,一个元素占俩坑 ) ; 往下一地方找找,如果再冲突,再找,直到找到一个可插入的地方,把 table[index] = key, table[index + 1] = value;
有两处需要注意:
key.hashCode() 必须是 2 的倍数, 否则 index 的值有可能为奇数,如此就可能发生冲突了. 可参考 ThreadLocal.hash 这个成员变量
table 内部的数据是分散着存储的.
2.连续的数组存储
这个以 Android 中新增的 ArrayMap 为例进行分析( 据说没 ArrayMap 是用来替换 HashMap 的哈 ), ArrayMap 中有两个主要变量, int[] mHashes, Object[] mArrays.
mHashes 主要是存放 key 的 hash 值的, mArrays 是用来存放数据的,它也是奇数存放 key ,偶数存放 value , key 和 value 顺序排列( 这个和 TheadLocal.value 中的 table 存储方式很像 )。 mArrays 的长度是 mHashes 的 2 倍,毕竟 mArrays 是 key, value 都要存嘛~
mHashes 中存放 key 的 hash 值,是从小到大排列的,如果有多个 key 的 hash 值有一样的,那么就挨着排列
当往 ArrayMap 中进行 put(key, value) 时,先 int hash = key.hashCode, 然后通过二分查找在 mHashes 中查找 hash 的位置( 如果里面有,就返回,如果无,就先找到最接近的位置,然后进行取反操作并返回 ) index,如果 index > 0 ,那么再去 mArrays 中 2 * index 处获取 key 值,比对两个 key 是否 equals(), 如果不相等,那么再分别向上、向下查找附近相同 hash 值的 key ,看是否有 equals() 的 key, 若有,则替换,若无,则插入; 如果 index < 0 ,表示之前没有相等 hash 的 key 插入过,那么 index = ~index( 再次取反,就是个正数了,代办要插入的位置), 再在 mHashes 的 index 处插入 hash, 在 mArrays 的 2 * index 处插入 key, 在 (2 * index ) + 1 处,插入 value .
注意:
mHashes 和 mArrays 在插入新数据时,都需要把插入位置后面的数据向后移动一个单位,这个对于频繁插入、删除的动作来说消耗比较大.
key 的 hash 大小决定了插入的顺序
3.以数字为 key 的数组存储
这类的 map 比较特殊,key 是数字类型。 这个以 Android 中新增的 SparseArray 进行分析。 SparseArray 中有两个主要变量, int[] mKeys 和 Object[] mValues , mKeys 是存放 key 的,是个有序数组,从小到大排列; mValues 是与 mKeys 一一对应的 value 值集合. mKeys 和 mValues 的长度是相等的。
当往 SparseArray 中 put(key, value) 时,先用二分查找在 mKeys 中查找 key 所在的位置 (如果找到,返回; 如果没有找到,则找到它应该插入的位置,取反并返回) ,记为 index, index > 0 ,则直接在 mValues[index] 处替换 value; 如果 index < 0 ,则 index = ~index, 即取反, 然后在 mKeys 的 index 处插入 key , 在 mValues[index] 处插入 value ,之前的数据自 index 处后移一个单位。
注意:
mKeys 和 mArrays 的数据插入时,都是要进行数据移动的,对频繁插入、删除的 map 来说消耗很大.
最后了,对它们的优缺点做些对比。
HashMap : 内存占用较大,增、删的效率较高,改、查的效率一般
ThreadLocal.Values : 内存占用一般,当数据量比较小时,增删改查的效率高;数据量大时,增删改查效率一般
ArrayMap: 内存占用较小,改、查的效率高,增、删的效率较低
SparseArray : 内存占用较小,改、查的效率高,增、删的效率低,且主键是数字
最后,我们不评判哪种存储方式好,一切都要以实际情况实际分析,找出最符合的那种存储,哈哈~
2. python字典是否有序
默认情况下Python的字典输出顺序是按照键的创建顺序。
字典的无序是指,不能人为重新排序。
比如说你按键值1,2,3,4的顺序创建的字典,只能由解析器按创建顺序,还是1,2,3,4的输出。
你无法控制它按照4,3,2,1的顺序输出,你也无法做到1,3,2,4的顺序。
而且这个输出顺序是也不是能真正按照创建顺序可以控的。
这里面有两个影响因素:
(1)键值的哈希碰撞,hash(key1) == hash(key2)时,向字典里连续添加的这个两个键的顺序是不可以控制的,也是无法做到连续的,后来的键会按算法调整到其它位置。
(2)字典空间扩容,当键的数量超过字典默认开的空间时,字典会做空间扩容,扩容后的键顺和创建顺序就会发生变化,不受人为控制。
3. Python中的字典是有顺序的吗
序列类型用有序的数字键做索引将数据以数组的形式存储。一般索引值与所存储的数据毫无关系。还可以用另一种方式来存储数据:基于
某种相关之,比如说一个字符串。
哈希表的算法是获取键,对键执行一个叫做哈希函数的操作,并根据计算的结果,选择在数据结构的某个地址中存储你的值。任何一个值
的地址皆取决与它的键。正因为这种随意性,哈希表中的值是没有顺序的。你拥有一个无序的数据集。
你所能获得的有序集合只能是字典中的键的集合或者值的集合。由于字典本身是哈希的,所以是无序的。
python学习网,免费的python学习网站,欢迎在线学习!
4. ios 字典循环存储后顺序变了吗
字典,不存在顺序吧
5. 字典可以排序吗
可以。
字典本身没有顺序概念,但是总是在某些时候,但是我们常常需要对字典进行排序,通常是按照key值排序。或者用sorted函数的key=参数排序,当然也有按照value排序的。
6. 新华字典上的字是按什么顺序排列的
《新华字典》全书按音序排列。
《新华字典》另附《部首检字表》。书中采用的部首与一般字典基本相同,但略有改动,共有189部。
如旧日字典的肉部、艸部、高部、鼓部、 齐部、龟部等都并省,而有些旧日字典根据《说文解字》、篆书的写法不分的,这本字典里都按楷书的写法分为两部,如“刀”与“刂”,“火”与“灬”,“心”与“忄“,“水” 与“氵”,便于查检。这种办法在中国字典中是前所未有的。
所收单字有8500个左右,在单字训解之下连带加出的复音词和词组有3200多个。复音词和词组都加有标志,这样就兼有简单词典之用。
(6)字典是顺序存储吗扩展阅读
《新华字典》最早的名字叫《伍记小字典》,但未能编纂完成。自1953年,开始重编,其凡例完全采用《伍记小字典》。从1953年开始出版,经过反复修订,但是以1957年商务印书馆出版的《新华字典》作为第一版。
原由新华辞书社编写,1956年并入中国科学院语言研究所(现中国社会科学院语言研究所)词典编辑室。《新华字典》由商务印书馆出版,历经几代上百名专家学者十余次大规模的修订,重印200多次,成为迄今为止世界出版史上最高发行量的字典。
《新华字典》是中国第一本按汉语拼音音序排列的小型字典。1953年新华辞书社编,主编者为语言文字学家魏建功(1901—1980)。1953年由人民教育出版社印行第一版,按注音字母顺序排列;以后续有修订,改用汉语拼音字母顺序,转由商务印书馆重排出版。
7. 顺序存储结构和链式存储结构优缺点
顺序存储结构和链式存储结构的区别
链表存储结构的内存地址不一定是连续的,但顺序存储结构的内存地址一定是连续的;
链式存储适用于在较频繁地插入、删除、更新元素时,而顺序存储结构适用于频繁查询时使用。
顺序存储结构和链式存储结构的优缺点:
空间上
顺序比链式节约空间。是因为链式结构每一个节点都有一个指针存储域。
存储操作上:
顺序支持随机存取,方便操作
插入和删除上:
链式的要比顺序的方便(因为插入的话顺序表也很方便,问题是顺序表的插入要执行更大的空间复杂度,包括一个从表头索引以及索引后的元素后移,而链表是索引后,插入就完成了)
例如:当你在字典中查询一个字母j的时候,你可以选择两种方式,第一,顺序查询,从第一页依次查找直到查询到j。第二,索引查询,从字典的索引中,直接查出j的页数,直接找页数,或许是比顺序查询最快的。
8. Python中的字典是什么
字典(Dictionary)
字典也是Python语言中经常使用的一种数据类型。跟列表类似,字典是另外一种可存储任意类型的数据,并且字典储存的数据也是可以修改的。
不同于列表的是,字典每个基本元素都包括两个部分:键(key) 和 键对应的值(value)。
- d = {"key1" : 1, "key2" : "hi", "key3":[]}
在字典中,键的内容是不可重复的。键为不可变数据类型,值可以是任何数据类型。在这里,键只支持字符串类型。
字典最大的优势就是能在海量数据下利用“键”快速查找出想要的值,当有很多数据需要存储的时候,我们给每个值都打个标签,也就是“键”;想要调用这个值时,字典能够利用这个标签快速帮我们找到它。但是如果标签重复了,字典不知道哪个值才是对的,就会报错哦~
列表是根据排序来记录每项的值,但是字典是没有顺序的,所以同一字典,每次打印出的排序可能是不同的。“键”才是调用字典的关键元素。
字典是基础的数据类型,所以变量也可以被赋值为字典。
键和值之间用冒号(:)分割,每对元素之间用逗号(,)分割,整个字典的数据在大括号{}中,格式如下所示: