博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java Map 怎样实现Key 的唯一性?
阅读量:6717 次
发布时间:2019-06-25

本文共 3797 字,大约阅读时间需要 12 分钟。

大家都知道。在Map和Set不可存在反复元素? 

可是对于内部的细节我们并不了解。今天我们就一块来 探讨一下!

1 对于 HashMap  HashSet  

他们的底层数据结构的实现是:维护了一张  HashTable 。容器中的元素所有存储在Hashtable 中。他们再加入元素的时候,是怎样推断是否存在有反复元素的呢?  每个被加入的元素都有一个 hashCode(哈希值),他们先比較哈希值,是否同样? 不同样的元素,加入进入 HashTable.   假设hashCode同样的话, 再去比較 equals()方法,假设也同样的话,JVM就觉得数据已经存在了。就不会加入数据!

如图1:

2 对于 TreeMap  TreeSet

他们底层是数据结构的实现是:维护了一棵二叉树。 容器中加入元素的时候,他们有是怎么推断是否有同样元素的?我们都直到 TreeMap TreeSet  她们 都是 有序的存储数据。

为了维护 数据的唯一性。 再存入数据的时候,他们会调用元素中 实现的 Comparable 的 compareTo()  方法(代码1)。 或者 集合本身创建的时候 传入了 迭代器(代码2).  详细的实现是:调用比較方法,返回-1 的时候,加入到左子树,返回1 的时候 加入到 右子树。

返回0 有同样数据 不加入该元素!

如图2

代码1;(原理一)

package stu.love.v;import java.util.*;//什么时候用Map/*当存在映射关系时。每一个学员都相应一个地址姓名,年龄同样的视为同一个人*/// 容器中的对象 本身 具备比較性。class StudentD implements Comparable
{ private String name; private int age; public StudentD(String name,int age) { this.name = name; this.age = age; } public int compareTo(StudentD stu) { int t = this.age-stu.age; return t==0?

this.name.compareTo(stu.name):t; } // 重写了 hashCode 方法 public int hashCode() { return name.hashCode()+age*36; } // 重写了 equals 方法 public boolean equals(Object obj) { if(!(obj instanceof StudentD)) throw new ClassCastException("类型异常"); StudentD stu =(StudentD)obj; return this.name.equals(stu.name) && this.age ==stu.age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public String getName() { return this.name; } public int getAge() { return this.age; } public String toString() { return this.name +","+age; } } class Demo16 { public static void main(String[] args) { //保证键唯一的原理,先推断哈希值是否同样,同样再推断equals() HashMap<StudentD,String> hm = new HashMap<StudentD,String>(); hm.put(new StudentD("xiaobai",23),"shanghai"); hm.put(new StudentD("wanghei",20),"beijing"); hm.put(new StudentD("lisi",28),"shenzhen"); hm.put(new StudentD("lisi",28),"shenzhen"); // Map 第一种 迭代方式 依据 key 找 value Set<StudentD> set=hm.keySet(); for(Iterator<StudentD> ite = set.iterator();ite.hasNext();) { StudentD stu = ite.next(); String value = hm.get(stu); sop(stu+"的地址是:"+value); } // map 的 另外一种 迭代方式 获取 键值对。entry 获取当中的 key 和 value Set<Map.Entry<StudentD,String>> entry = hm.entrySet(); for(Iterator<Map.Entry<StudentD,String>> ite = entry.iterator();ite.hasNext();) { Map.Entry<StudentD,String> kv = ite.next(); StudentD key = kv.getKey(); String value = kv.getValue(); sop(key+"的地址是:"+value); } } public static void sop(Object obj) { System.out.println(obj); } }

代码2:

package stu.love.v;/*TreeMap:HashMap保证键唯一的原理和HashSet同样TreeMap保证键唯一的原理和TreeSet同样*/import java.util.*;class Student1{	private String name;	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}	public int getAge() {		return age;	}	public void setAge(int age) {		this.age = age;	}	private int age;		public Student1(String name,int age)	{		this.name = name;		this.age = age;	}			public String toString()	{		return name+","+age;	}	}//  比較器class CompareByName implements Comparator
{ public int compare(Student1 s1,Student1 s2) {// 这样写的方法 很好!

简洁 int t = s1.getName().compareTo(s2.getName()); return t ==0?s1.getAge()-s2.getAge():t; } } class Demo17 { public static void main(String[] args) { // 原理二: //保证键唯一的原理:比較方法的返回值为0 TreeMap<Student1,String> tm = new TreeMap<Student1,String>(new CompareByName()); tm.put(new Student1("xiaobai",23),"shanghai"); tm.put(new Student1("wanghei",20),"beijing"); tm.put(new Student1("lisi",28),"shenzhen"); tm.put(new Student1("lisi",28),"shenzhen"); Set<Map.Entry<Student1,String>> entry = tm.entrySet(); for(Iterator<Map.Entry<Student1,String>> it = entry.iterator();it.hasNext();) { Map.Entry<Student1,String> kv = it.next(); Student1 key = kv.getKey(); String value = kv.getValue(); sop(key+"的地址是:"+value); } } public static void sop(Object obj) { System.out.println(obj); } }

你可能感兴趣的文章
linux下切割catalina.out文件,按天生成文件
查看>>
macOS 下的 Eclipse.ini 文件在哪?
查看>>
UVA - 10785 The Mad Numerologist
查看>>
44.3. Image Charts
查看>>
[ACM_数据结构] HDU 1166 敌兵布阵 线段树 或 树状数组
查看>>
SaveFileDialog与Castle(ActiveRecord)有冲突??
查看>>
C#~异步编程再续~await与async引起的w3wp.exe崩溃
查看>>
指针,c语言的灵魂
查看>>
[Erlang 0005] net_kernel:monitor_nodes 订阅node连接\断开消息
查看>>
第 30 章 Linux
查看>>
5.5. git-daemon 服务器
查看>>
浅谈Windows环境下DOS及MS-DOS以及常见一些命令的介绍
查看>>
工具系列~WebMatrix搭建WEB站点
查看>>
JAVA 之 多态 抽象 接口
查看>>
[LintCode] Integer to Roman 整数转化成罗马数字
查看>>
日期控件
查看>>
mysql 如何修改、添加、删除表主键
查看>>
【Maven】3.使用IntelliJ IDEA 使用本地搭建的maven私服,而不是使用默认的maven设置...
查看>>
Navi.Soft31.WinForm框架(含下载地址)
查看>>
Charles配置抓包HTTP,HTTPS
查看>>