针对HashMap的自定义排序

本文介绍了HashMap的自定义排序方法,首先讲解了Hash函数和HashCode的概念及其在HashMap中的作用,然后通过示例代码展示了如何按照value和key对HashMap进行排序。通过对HashMap的entrySet排序并使用Collections.sort(),可以实现按照value的降序排列;而使用TreeMap则可以自动按照key进行升序排序。

要对 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 的自定义排序

 

 

      

在 Java 中,对 `List<Map>` 结构按照特定字段进行排序是一种常见的需求,尤其是在处理从数据库查询返回的动态数据时。可以通过 `Collections.sort()` 方法结合自定义的 `Comparator` 来实现这一功能。 以下是一个示例,展示了如何根据 `Map` 中的某个键(例如 `"age"`)来对 `List<Map<String, Object>>` 进行排序: ```java import java.util.*; public class MapListSorter { public static void main(String[] args) { List<Map<String, Object>> list = new ArrayList<>(); // 添加测试数据 Map<String, Object> person1 = new HashMap<>(); person1.put("name", "Alice"); person1.put("age", 30); list.add(person1); Map<String, Object> person2 = new HashMap<>(); person2.put("name", "Bob"); person2.put("age", 25); list.add(person2); Map<String, Object> person3 = new HashMap<>(); person3.put("name", "Charlie"); person3.put("age", 35); list.add(person3); // 使用 Comparator 对 list 按照 "age" 字段排序 list.sort(Comparator.comparing(map -> (Integer) map.get("age"))); // 打印排序后的结果 for (Map<String, Object> map : list) { System.out.println(map); } } } ``` ### 说明: - 上述代码中使用了 `list.sort()` 方法,并传入了一个基于 `map.get("age")` 的比较器。 - 通过 `(Integer) map.get("age")` 获取值并进行类型转换,确保排序逻辑正确执行 [^2]。 - 如果需要降序排序,可以将比较器改为 `Comparator.comparing(map -> (Integer) map.get("age")).reversed()`。 ### 静态成员变量优化 为了减少每次排序时创建匿名类带来的内存开销,可以将比较器定义为静态成员变量或静态常量。例如: ```java public class MapListSorter { // 定义一个静态比较器 private static final Comparator<Map<String, Object>> AGE_COMPARATOR = Comparator.comparing(map -> (Integer) map.get("age")); public static void main(String[] args) { List<Map<String, Object>> list = new ArrayList<>(); // 添加测试数据 Map<String, Object> person1 = new HashMap<>(); person1.put("name", "Alice"); person1.put("age", 30); list.add(person1); Map<String, Object> person2 = new HashMap<>(); person2.put("name", "Bob"); person2.put("age", 25); list.add(person2); Map<String, Object> person3 = new HashMap<>(); person3.put("name", "Charlie"); person3.put("age", 35); list.add(person3); // 使用静态比较器进行排序 list.sort(AGE_COMPARATOR); // 打印排序后的结果 for (Map<String, Object> map : list) { System.out.println(map); } } } ``` 这种方法避免了在每次调用排序方法时重新创建比较器对象,从而减少了垃圾回收的压力 [^2]。 ### 多字段排序 如果需要根据多个字段进行排序,比如先按年龄升序,再按姓名升序,可以使用链式调用的方式: ```java list.sort(Comparator.comparing((Map<String, Object> map) -> (Integer) map.get("age")) .thenComparing(map -> (String) map.get("name"))); ``` 这种写法允许你灵活地指定多个排序条件,适用于更复杂的业务场景。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值