Java HashMap如何实现Key 的唯一性
大家都知道,在Map和Set不可存在重复元素? 但是对于内部的细节我们并不了解,今天我们就一块来 探讨一下!1 对于 HashMap HashSet 他们的底层数据结构的实现是:维护了一张 HashTable 。容器中的元素全部存储在Hashtable 中。他们再添加元素的时候,是如何判断是否存在有重复元素的呢? 每一个被添加的元素都有一个 hashCo
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<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);
- }
- }
更多推荐
所有评论(0)