Java Map 怎样实现Key 的唯一性?
大家都知道。在Map和Set不可存在反复元素?
可是对于内部的细节我们并不了解。今天我们就一块来 探讨一下!
1 对于 HashMap HashSet
他们的底层数据结构的实现是:维护了一张 HashTable 。容器中的元素所有存储在Hashtable 中。他们再加入元素的时候,是怎样推断是否存在有反复元素的呢? 每个被加入的元素都有一个 hashCode(哈希值),他们先比較哈希值,是否同样? 不同样的元素,加入进入 HashTable. 假设hashCode同样的话, 再去比較 equals()方法,假设也同样的话,JVM就觉得数据已经存在了。就不会加入数据!
如图1:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbG92ZV9KYXZjX3lvdQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
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<StudentD>
{
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<Student1>
{
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);
}
}
Java Map 怎样实现Key 的唯一性?的更多相关文章
- Java Map集合按照key和value排序之法
一.理论基点 Map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等. TreeMap:基于红黑树(Red-Black-Tre ...
- java map遍历、排序,根据value获取key
Map 四种遍历: Map<String,String> map = new HashMap<String, String>(); map.put("one" ...
- Java Map获取key和value 以及String字符串转List方法
一.问题描述 这里描述两个问题: 1.Java Map获取key和value的方法: 2.String字符串转List的方法: 二.解决方法 1.Java Map获取key和value的方法 2. ...
- [Android] View.setTag(key,Object) (java.lang.IllegalArgumentException: The key must be an application-specific resource id.)
转自: http://blog.csdn.net/brokge/article/details/8536906 setTag是android的view类中很有用的一个方法,可以用它来给空间附加一些信息 ...
- java Map实现的cache manager
一个模仿memcached的JAVA虚拟缓存工具,可以缓存java对象 import java.io.ByteArrayInputStream; import java.io.ByteArrayOut ...
- Java map 详解 - 用法、遍历、排序、常用API等
尊重原创: http://www.cnblogs.com/lzq198754/p/5780165.html 概要: java.util 中的集合类包含 Java 中某些最常用的类.最常用的集合类是 L ...
- Java Map用法
Map简介 将键映射到值的对象.一个映射不能包含重复的键:每个键最多只能映射到一个值.此接口取代 Dictionary类,后者完全是一个抽象类,而不是一个接口. Map 接口提供三种collectio ...
- Java Map 及相应的一些操作总结
Map是我们在开发的时候经常会用到的,大致有以下几个操作,其中putAll方法是针对集合而言的操作,故不再进行说明,下面请看一下常用的知识点吧,尤其是keySet和Values两个方法及相应值的获取方 ...
- Java Map 集合实现类
Map 用于保存具有映射关系的数据,集合里会保存两组值,一组用于保存Map里的key,一组用于保存Map里的value,key与map可以是任何引用类型数据.Map的key不允许重复.key与valu ...
随机推荐
- 实现div左右上下都居中
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- [ TJOI 2010 ] 打扫房间
\(\\\) Description 给出一个\(N\times M\) 的网格,一些格子是污点,求是否能用多个封闭的环路覆盖所有不是污点的格点. 封闭的环路覆盖的含义是,每条路径都必须是一个环,且每 ...
- python manage.py syncdb报错:No module named MySQLdb
今天同步数据时出现这个错误: 解决方法: 1.先下载mysql-python 支持1.2.3-2.7版本 MySQL-python 1.2.3 for Windows and Python 2.7, ...
- Android开发: 关于性能需要考虑的
刚做Android开发时,只管完成任务,将需求完成,以能完成一款界面酷炫的app为自豪.然而,随着代码量的增加,越来越意识到,一款成功的移动端产品,光有酷炫的外衣还不够,还需要在各方面都优秀. 试想, ...
- 对比hive和mysql查询汇总
由于底层的处理机制大不相同,hive和mysql在查询上还是有较大差异的! 单个表的select操作 最简单的查询 ,字段2 frome 表名 where 字段 [not]in(元素1,元素2): 例 ...
- Zynq7000系列之芯片引脚功能综述
很多人做了很久的FPGA,知道怎么去给信号分配引脚,却对这些引脚的功能及其资源限制知之甚少:在第一章里对Zynq7000系列的系统框架进行了分析和论述,对Zynq7000系列的基本资源和概念有了大致的 ...
- 安卓app测试之启动时间和电量监控
一.启动时间监控 通过adb命令获取 adb shell am start -W /<packageName> /<activityName> 案例: adb shell am ...
- 并发编程学习笔记(12)----Fork/Join框架
1. Fork/Join 的概念 Fork指的是将系统进程分成多个执行分支(线程),Join即是等待,当fork()方法创建了多个线程之后,需要等待这些分支执行完毕之后,才能得到最终的结果,因此joi ...
- 梦想CAD控件关于标注的系统变量说明
主要用到函数说明: IMxDrawDimension::SetDimVarDouble 设置标注属性的实数类型变量值,详细说明如下: 参数 说明 [in] LONG iType 该属性的类形值 dVa ...
- java_线程类的基本功能
Thread类是实现了Runnable接口 其方法有: start()开始:开始线程 run()跑:线程内容 currentThread()现在的线程:返回当前线程 getName():获取线程名 s ...