java基础36 双例集合Map下的HashMap和TreeMap集合
单例集合体系:
---------| collection 单例集合的根接口
--------------| List 如果实现了list接口的集合类,具备的特点:有序,可重复 注:集合中的有序不是指自然顺序,而是指添加进去的顺序与出来的顺序是一致的
------------------| ArrayList ArrayList底层维护了一个object数组的实现的。(线程不安全),特点:查询速度快,增删速度慢。(有序,可重复)
------------------| LinkedList LinkedList底层是使用链表结构实现的,线程不安全,特点:查询速度慢,增删速度快。(有序,可重复)
------------------| Vector(了解即可) 底层也是维护一个Object数组的实现的,实现与ArrayList是一样的,但是Vector是线程安全的,操作效率低
--------------| Set 如果实现了set接口的集合类,具备的特点:无序,不可重复 注:集合中的无序不是指自然顺序,而是指添加元素进去的顺序与元素出来的顺序是不一致的
------------------| HashSet 底层是用于一个哈希表支持的,线程不安全,特点:存储速度块
------------------| TreeSet 底层是使用红黑树(二叉树)数据结构实现的,线程不同步(即线程不安全),不能在多线程中共享,但可以使用synchroinzedMap()方法来实现同步。特点:会对元素进行排序存储(按自然顺序)
双例集合体系:
----------| Map 双例集合的根接口。如果是实现了Map接口的集合类,具备的特点:存储的数据都是以键值对形式存在的,键不可重复,值可以重复
--------------| HashMap 底层是基于哈希表实现的,HashMap允许键和值为null,线程不安全,特点:存储速度块
--------------| TreeMap 基于红黑数(二叉树)数据结构实现的,线程不同步(即线程不安全),特点:会对元素经行排序存储
--------------| HashTable(了解即可) 线程安全
一、HashMap集合
1.1、HashMap集合的一些常用方法
1.2、HashMap的存储原理
往HasMap集合中添加元素时,首先会调用键的hashCode()方法得到元素的哈西马值,然后经过运算在哈希表找到相应存储位置
情况1:如果算出的位置目前没有任何元素,那么该元素可以直接添加到哈希表中。
情况2:如果算出元素的位置已经存在其他元素,那么就会调用equals方法与该元素位置已存在的元素做一次比较;如过equals方法返回值是true,那么该元素是重复元素,不允许存储;如果返回值是false,那么该元素不是重复元素,则允许存储。
1.3、HashMap和HashSet的区别
相同点:
1.集合中元素都是无序,不可重复。且都要重写HashCode和equals方法进行判断比较。注:“无序”指添加元素进去(集合)的顺序与元素输出来的顺序是不一致的。指定的比较字段不可重复,但 非指定字段可重复
2.都是线程不安全的
不同点:
1.HashMap实现了Map接口;HashSet实现了Set接口。
2.HashMap是以键值对的形式储存的;HashSet存储的是对象。
3.HashMap比较快,因为使用的是唯一的键来获取对象;HashSet较HashMap来说,比较慢。
4.HashMap是使用put()方法将元素放入map集合中;而HashSet是使用add()方法将元素放入set集合中。
1.4、实例
例1 (没有重写HashCode和equals方法的结果:“110,狗娃”这个重复元素,两个都添加进map集合中)
package com.dhb.collection; import java.util.HashMap; /** * @author DSHORE / 2018-5-30 * */ class Personnal{ int id; String name; public Personnal(int id, String name) { super(); this.id = id; this.name = name; } @Override public String toString() { return "Personnal [id=" + id + ",name=" + name + "]"; } } public class Demo22 { public static void main(String[] args) { HashMap<Personnal, String> map=new HashMap<Personnal, String>(); map.put(new Personnal(110,"狗娃"),"001"); map.put(new Personnal(220,"狗剩"), "002"); map.put(new Personnal(330,"狗蛋"),"003"); map.put(new Personnal(110,"狗娃"),"007"); System.out.println("集合中的元素:"+map);//返回值:{Personnal [id=330,name=狗蛋]=003, Personnal [id=220,name=狗剩]=002, Personnal [id=110,name=狗娃]=001, Personnal [id=110,name=狗娃]=007} } }
例2 (重写HashCode和equals方法后的结果:“110,狗娃”这个重复元素,只有一个添加进map集合中)
1 package com.dhb.collection; 2 3 import java.util.HashMap; 4 5 /** 6 * @author DSHORE / 2018-5-30 7 * 8 */ 9 class Personnal{ 10 int id; 11 String name; 12 13 public Personnal(int id, String name) { 14 super(); 15 this.id = id; 16 this.name = name; 17 } 18 @Override 19 public String toString() { 20 return "Personnal [id=" + id + ",name=" + name + "]"; 21 } 22 @Override 23 public int hashCode() {//重写hashCode方法 24 return this.id; 25 } 26 @Override 27 public boolean equals(Object obj) {//重写equals方法 28 Personnal p = (Personnal) obj; 29 return this.id == p.id; //指定的比较字段不可重复,但,非指定字段可重复 30 } 31 } 32 public class Demo22 { 33 public static void main(String[] args) { 34 HashMap<Personnal, String> map=new HashMap<Personnal, String>(); //注:“无序”指添加元素进去(集合)的顺序与元素输出来的顺序是不一致的。 35 map.put(new Personnal(110,"狗娃"),"001"); //指定的比较字段不可重复,但,非指定字段可重复。 110是指定比较字段,狗娃不是 36 map.put(new Personnal(220,"狗剩"), "002"); 37 map.put(new Personnal(330,"狗蛋"),"003"); 38 map.put(new Personnal(110,"狗娃"),"007"); 39 System.out.println("集合中的元素:"+map);//返回值:{Personnal [id=220,name=狗剩]=002, Personnal [id=110,name=狗娃]=007, Personnal [id=330,name=狗蛋]=003} 40 } 41 }
重写HashCode和equals方法后,例2比例1少了一个id为110的重复值
二、TreeMap集合
2.1、TreeMap集合的一些常用方法
2.2、TreeMap需要注意的事项
1.往TrreMap添加元素时候,如果元素本身具备自然顺序时,那么就按照自然顺序排列存储。
2.往TrreMap添加元素时候,如果元素本身不具备自然顺序,那么键所属的类必须要实现Comparable接口,把键比较的规则定义在CompareTo方法中。
3.往TrreMap添加元素时候,如果元素本身不具备自然顺序,键所属的类也没有实现Comparable接口,那么必须在创建TreeMap是传入一个比较器。
2.3、自定义比较器
自定一个比较器只需要实现接口 Comparator<T>即可,把元素与元素之间的比较规则定义在compare方法内即可
自定义比较器的格式: class 类名 implements Comparator<T>{ }
实例 (通过自定义比较器来排序存储)
1 package com.dhb.collection; 2 3 import java.util.Comparator; 4 import java.util.TreeMap; 5 6 /** 7 * @author DSHORE / 2018-5-30 8 * 9 */ 10 class Emp3{ 11 String name; 12 int salary; 13 public Emp3(String name,int salary) { 14 this.name=name; 15 this.salary=salary; 16 } 17 @Override 18 public String toString() { 19 return "Emp [name=" + name + ",salary=" + salary + "]"; 20 } 21 } 22 //自定义比较器 作用:用于根据指定字段进行比较 排序存储 23 class MyComparator1 implements Comparator<Emp3>{ 24 25 public int compare(Emp3 o1, Emp3 o2) { 26 return o1.salary-o2.salary; 27 } 28 } 29 public class Demo23 { 30 public static void main(String[] args) { 31 MyComparator1 mc=new MyComparator1();//创建比较器MyComparator1对象 32 TreeMap<Emp3, Integer> tm=new TreeMap<Emp3, Integer>(mc); 33 tm.put(new Emp3("张三",2000),1); 34 tm.put(new Emp3("李四",1000), 2); 35 tm.put(new Emp3("王五",36000),3); 36 tm.put(new Emp3("赵六",5000), 4); 37 38 System.out.println(tm);//返回值:{Emp [name=李四,salary=1000]=2, Emp [name=张三,salary=2000]=1, Emp [name=赵六,salary=5000]=4, Emp [name=王五,salary=36000]=3} 39 } 40 }
2.4、TreeMap和TreeSet的区别
相同点:
1.都是无序集合(添加进去和输出来的顺序不一样),但是,存储方式都是一样的,都是按自然顺序排序存储的。
2.都是非同步集合(线程不安全),因此他们不能在多线程之间共享,不过可以使用方法Collections.synchroinzedMap()来实现同步。
3.运行速度都要比Hash集合慢。
不同点:
1.TreeMap实现了Map接口;TreeSet实现了Set接口。
2.TreeMap是以键值对的形式储存的;TreeSet存储的是对象。
3.TreeMap是使用put()方法将元素放入map集合中;而TreeSet是使用add()方法将元素放入set集合中。
2.5、实例
通过实现Comparable<T>接口来 排序存储
1 package com.dhb.collection; 2 3 import java.util.TreeMap; 4 5 /** 6 * @author DSHORE / 2018-5-30 7 * 8 */ 9 class Emp4 implements Comparable<Emp4>{ //实现Comparable<T>接口 10 String name;//姓名 11 int salary;//工资 12 public Emp4(String name,int salary) { 13 this.name=name; 14 this.salary=salary; 15 } 16 @Override 17 public String toString() { 18 return "Emp [name=" + name + ",salary=" + salary + "]"; 19 } 20 @Override 21 public int compareTo(Emp4 e) {//实现Comparable接口后,重写compareTo方法 22 return this.salary - e.salary;//用工资进行排序存储 23 } 24 } 25 public class Demo24 { 26 public static void main(String[] args) { 27 TreeMap<Emp4, Integer> tm=new TreeMap<Emp4, Integer>(); 28 tm.put(new Emp4("张三",2000),1); 29 tm.put(new Emp4("李四",1000), 2); 30 tm.put(new Emp4("王五",36000),3); 31 tm.put(new Emp4("赵六",5000), 4); 32 33 System.out.println(tm);//返回值:{Emp [name=李四,salary=1000]=2, Emp [name=张三,salary=2000]=1, Emp [name=赵六,salary=5000]=4, Emp [name=王五,salary=36000]=3} 34 } 35 }
原创作者:DSHORE 作者主页:http://www.cnblogs.com/dshore123/ 原文出自:https://www.cnblogs.com/dshore123/p/9110016.html 欢迎转载,转载务必说明出处。(如果本文对您有帮助,可以点击一下右下角的 推荐,或评论,谢谢!) |