要对 HashMap 进行自定义排序,首先要了解 HashMap 本身是根据什么排序的。在进行之前,我们应该首先了解 Hash 函数和 HashCode 。
Hash
,一般翻译做"散列",也有直接音译为"哈希"的,就是把任意长度的输入(又叫做预映射,
pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不
同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。
简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
HASH主要用于信息安全领域中加密算法,他把一些不同长度的信息转化成杂乱的128位的编码里,叫做HASH值. 也可以说,hash就是找到一种数据内容和数据存放地址之间的映射关系
- hash函数就是把任意长度的输入(又叫做预映射,
pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。
例如,散列算法为求余的hash函数。 - 实际中的Hash函数是指把一个大范围映射到一个小范围。把大范围映射到一个小范围的目的往往是为了节省空间,使得数据容易保存。
- 在数据结构中,hash就是找到一种数据内容和数据存放地址之间的映射关系,比如,31对10求余后得1,就把31存放到第一个桶里(或者是第一块内存单元中),即把数据和存放地址建立映射关系。
- 有了数据内容和数据存放地址之间的映射关系,Hash函数往往应用于查找上。不过,利用hash函数的查找跟以前自己理解的不同,以前自己以为是通过 hash 函数就能立即找到存储地址,就像HashMap中根据key立即能找到value 一样,其实不是这样的,hash 函数只不过是根据散列算法和解决 冲突的方法来提供一种定位和查找的方式,hashmap中根据可以马上找到value值是理所当然的,但是根据hash函数找到key值就不是立即的了。 当然,为了方便查找,尽量使得hash函数无冲突,可以唯一确定地址是最理想的。
- Hash函数是指把一个大范围映射到一个小范围,所以hash函数是求余之类的压缩函数,(比如,11,13的范围压缩为1,3),而不是10x+7这样的扩散函数,(比如,11,13的范围扩散为117,137)。
- 由于 Hash 逼近单向函数;所以,你可以用它来对数据进行加密。
- 不同的应用对 Hash 函数有着不同的要求;比如,用于加密的Hash函数主要考虑它和单项函数的差距,而用于查找的Hash函数主要考虑它映射到小范围的冲突率。
上面这些概念是从网上 Copy 的,自己看着有点云里雾里,但是好歹还算理解个大致的意思。不过这对理解 HasMap 排序原理已经足够了。知道了 Hash 那下面就要说下 HasCode(散列码)了
HashCode
- hashCode()是用来产生哈希玛的,而哈希玛是用来在散列存储结构中确定对象的存储地址的。
- HashMap,HashSet, 他们在将对象存储时(严格说是对象引用),需要确定他们的地址吧, 而HashCode()就是这个用途的,一般都需要重新定义它的,因为默认情况下,由 Object 类定义的 hashCode 方法会针对不同的对象返回不同的整数,这一般是通过将该对象的内部地址转换成一个整数来实现的,现在举个例子来说, 就拿HashSet来说 ,在将对象存入其中时,通过被存入对象的 hashCode() 来确定对象在 HashSet 中的存储地址,通过equals()来确定存入的对象是否重复,hashCode() ,equals()都需要自己重新定义,因为hashCode()默认前面已经说啦,而equals() 默认是比较的对象引用,你现在想一下,如果你不定义equals()的话,那么同一个类产生的两个内容完全相同的对象都可以存入Set,因为他们是通过 equals()来确定的,这样就使得HashSet 失去了他的意义
OK!万事俱备,只欠代码!下面开始实现 HashMap 的自定义排序
本文介绍了HashMap的自定义排序方法,首先讲解了Hash函数和HashCode的概念及其在HashMap中的作用,然后通过示例代码展示了如何按照value和key对HashMap进行排序。通过对HashMap的entrySet排序并使用Collections.sort(),可以实现按照value的降序排列;而使用TreeMap则可以自动按照key进行升序排序。
1075

被折叠的 条评论
为什么被折叠?



