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 ...
随机推荐
- MAMP中Python安装MySQLdb
Python 标准数据库接口为 Python DB-API,Python DB-API为开发人员提供了数据库应用编程接口. MySQLdb 是用于Python链接Mysql数据库的接口,它实现了 Py ...
- Android 网络图片查看器与网页源码查看器
在AndroidManifest.xml里面先添加访问网络的权限: <uses-permission android:name="android.permission.INTERNET ...
- NX自动出图 效果图
- 全3D模具设计自动化解決方案
- mysql复制过滤参数说明
参考文档: http://www.ywnds.com/?p=6945 https://stackoverflow.com/questions/23191160/whats-the-difference ...
- (转)Hibernate框架基础——映射集合属性
http://blog.csdn.net/yerenyuan_pku/article/details/52745486 集合映射 集合属性大致有两种: 单纯的集合属性,如像List.Set或数组等集合 ...
- public private protected
初学C++的朋友经常在类中看到public,protected,private以及它们在继承中表示的一些访问范围,很容易搞糊涂.今天本文就来十分分析一下C++中public.protected及pri ...
- Navicat for MySQL(Ubuntu)过期解决方法
推荐购买正版软件,尊重版权 [官网在这里] Navicat for MySQL(Ubuntu系统)免费版试用过期解决方法: Step1. 直接删除 /home目录下的 .navicat文件夹(64 ...
- TestNG套件测试(一)
测试套件是用于测试软件程序的行为或一组行为的测试用例集合. 在TestNG中,我们无法在测试源代码中定义一个套件,但它可以由一个XML文件表示,可以灵活配置要运行的测试. 套件用<suite&g ...
- 【Codeforces 464A】No to Palindromes!
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 因为原序列没有任何长度超过2的回文串. 所以,我们在改变的时候,只要时刻保证改变位置s[i]和s[i-1]以及s[i-2]都不相同就好. 因为 ...