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 ...
随机推荐
- mybatis 关联查询
1.关联的两个实体类 外部类 parent public class Parent{ private String parentId; private String parentName; priva ...
- Linux 学习(四)
搭建jdk 安装jdk操作: 1.光驱挂载:mount /dev/cdrom /mnt 2.拷贝安装包至其他文件夹(如home目录下) 3.执行安装包(bin包:./包名) 4.配置环境变量:打开文件 ...
- BZOJ 3884: 上帝与集合的正确用法 扩展欧拉定理 + 快速幂
Code: #include<bits/stdc++.h> #define maxn 10000004 #define ll long long using namespace std; ...
- 梦想CAD控件COM接口搜索图面上的文字
点击此处下载演示实例 主要用到函数说明: _DMxDrawX::NewSelectionSet 实例化一个构造选择集进行过滤,该类封装了选择集及其处理函数. _DMxDrawX::NewResbuf ...
- 并发和多线程(三)--并发容器J.U.C和lock简介
AQS: 是AbstractQueuedSynchronizer的简称,JUC的核心 底层是sync queue双向链表,还可能有condition queue单向链表,使用Node实现FIFO队列, ...
- java基础学习日志--异常案例
package test7; public class InvalidScroreException extends Exception { public InvalidScroreException ...
- python面向对象的特点,类定义等,私有属性、公有属性、成员属性
引子:类的对象在内存中的表示def dog(name,dog_type): def bark(d): print(d,'wang wang wang ...') data = { 'name':nam ...
- ubuntu tomcat自启动
1 编写启动文件/etc/init.d/tomcat7 文件内容如下:
- 1289大鱼吃小鱼(STL中栈的应用)
>>点击进入测试<< 有N条鱼每条鱼的位置及大小均不同,他们沿着X轴游动,有的向左,有的向右.游动的速度是一样的,两条鱼相遇大鱼会吃掉小鱼.从左到右给出每条鱼的大小和游动的方向 ...
- POJ -棋盘问题
棋盘问题 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 60815 Accepted: 29135 Descriptio ...