大家都知道,在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:(原理一)

[java]  view plain copy print ?
  1. package stu.love.v;  
  2.   
  3. import java.util.*;  
  4. //什么时候用Map  
  5. /* 
  6. 当存在映射关系时, 
  7. 每个学员都对应一个地址 
  8. 姓名,年龄相同的视为同一个人 
  9.  
  10. */  
  11. // 容器中的对象 本身 具备比较性!  
  12.   
  13. class StudentD implements Comparable<StudentD>  
  14. {  
  15.     private String name;  
  16.     private int age;  
  17.       
  18.     public StudentD(String name,int age)  
  19.     {  
  20.         this.name = name;  
  21.         this.age = age;  
  22.     }  
  23.       
  24.     public int compareTo(StudentD stu)  
  25.     {  
  26.         int t = this.age-stu.age;  
  27.         return t==0?this.name.compareTo(stu.name):t;  
  28.     }  
  29.       
  30.       
  31. //  重写了 hashCode 方法  
  32.     public int hashCode()  
  33.     {  
  34.         return name.hashCode()+age*36;  
  35.     }  
  36.     
  37. //    重写了  equals 方法  
  38.     public boolean equals(Object obj)  
  39.     {   
  40.        if(!(obj instanceof StudentD))  
  41.             throw new ClassCastException("类型异常");  
  42.          
  43.         StudentD stu =(StudentD)obj;  
  44.         return this.name.equals(stu.name) && this.age ==stu.age;  
  45.     }  
  46.     
  47.     
  48.     public void setName(String name)  
  49.     {  
  50.         this.name = name;  
  51.     }  
  52.     public void setAge(int age)  
  53.     {  
  54.         this.age = age;  
  55.     }  
  56.     public String getName()  
  57.     {  
  58.         return this.name;  
  59.     }  
  60.     public int getAge()  
  61.     {  
  62.         return this.age;  
  63.     }  
  64.     public String toString()  
  65.     {  
  66.         return this.name +","+age;  
  67.     }  
  68. }  
  69. class Demo16   
  70. {  
  71.     public static void main(String[] args)   
  72.     {     
  73.         //保证键唯一的原理,先判断哈希值是否相同,相同再判断equals()  
  74.         HashMap<StudentD,String> hm = new HashMap<StudentD,String>();  
  75.   
  76.         hm.put(new StudentD("xiaobai",23),"shanghai");  
  77.         hm.put(new StudentD("wanghei",20),"beijing");  
  78.         hm.put(new StudentD("lisi",28),"shenzhen");  
  79.         hm.put(new StudentD("lisi",28),"shenzhen");  
  80.   
  81.        
  82. //      Map 第一种 迭代方式   根据 key 找  value  
  83.         Set<StudentD> set=hm.keySet();  
  84.         for(Iterator<StudentD>  ite = set.iterator();ite.hasNext();)  
  85.         {  
  86.             StudentD stu = ite.next();  
  87.             String value = hm.get(stu);  
  88.             sop(stu+"的地址是:"+value);  
  89.         }  
  90.        
  91. //      map 的 第二种 迭代方式  获取 键值对,entry 获取其中的 key 和 value  
  92.         Set<Map.Entry<StudentD,String>> entry = hm.entrySet();  
  93.         for(Iterator<Map.Entry<StudentD,String>> ite = entry.iterator();ite.hasNext();)  
  94.         {  
  95.             Map.Entry<StudentD,String> kv = ite.next();  
  96.             StudentD key = kv.getKey();  
  97.             String  value = kv.getValue();  
  98.             sop(key+"的地址是:"+value);  
  99.         }  
  100.       
  101.       
  102.     }  
  103.   
  104.     public static void sop(Object obj)  
  105.     {  
  106.         System.out.println(obj);  
  107.     }  
  108. }  

 

代码2:

[java]  view plain copy print ?
  1. package stu.love.v;  
  2.   
  3. /* 
  4. TreeMap: 
  5. HashMap保证键唯一的原理和HashSet相同 
  6. TreeMap保证键唯一的原理和TreeSet相同 
  7.  
  8. */  
  9. import java.util.*;  
  10.   
  11.   
  12. class Student1  
  13. {  
  14.     private String name;  
  15.     public String getName() {  
  16.         return name;  
  17.     }  
  18.   
  19.   
  20.     public void setName(String name) {  
  21.         this.name = name;  
  22.     }  
  23.   
  24.   
  25.     public int getAge() {  
  26.         return age;  
  27.     }  
  28.   
  29.   
  30.     public void setAge(int age) {  
  31.         this.age = age;  
  32.     }  
  33.   
  34.   
  35.     private int age;  
  36.       
  37.     public Student1(String name,int age)  
  38.     {  
  39.         this.name = name;  
  40.         this.age = age;  
  41.     }  
  42.       
  43.       
  44.     public String toString()  
  45.     {  
  46.         return name+","+age;  
  47.     }  
  48.       
  49. }  
  50.   
  51.   
  52.   
  53. //  比较器  
  54. class CompareByName implements Comparator<Student1>  
  55. {  
  56.     public int compare(Student1 s1,Student1 s2)  
  57.     {  
  58. //      这样写的方法 非常好!  简洁  
  59.         int t = s1.getName().compareTo(s2.getName());  
  60.         return t ==0?s1.getAge()-s2.getAge():t;  
  61.     }  
  62. }  
  63.   
  64. class  Demo17  
  65. {  
  66.     public static void main(String[] args)   
  67.     {    
  68. //      原理二:  
  69.         //保证键唯一的原理:比较方法的返回值为0  
  70.         TreeMap<Student1,String> tm = new TreeMap<Student1,String>(new CompareByName());  
  71.           
  72.         tm.put(new Student1("xiaobai",23),"shanghai");  
  73.         tm.put(new Student1("wanghei",20),"beijing");  
  74.         tm.put(new Student1("lisi",28),"shenzhen");  
  75.         tm.put(new Student1("lisi",28),"shenzhen");  
  76.   
  77.         Set<Map.Entry<Student1,String>> entry = tm.entrySet();  
  78.           
  79.         for(Iterator<Map.Entry<Student1,String>> it = entry.iterator();it.hasNext();)  
  80.         {  
  81.             Map.Entry<Student1,String> kv = it.next();  
  82.             Student1 key = kv.getKey();  
  83.             String  value = kv.getValue();  
  84.             sop(key+"的地址是:"+value);  
  85.         }  
  86.     }  
  87.     public static void sop(Object obj)  
  88.     {  
  89.         System.out.println(obj);  
  90.     }  
  91. }  
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐