(三十九)HashMap、HashTable、TreeMap、WeakHashMap有什么区别
java.util.Map接口三个实现类:
—Hashtable:底层是哈希表数据结构,不可以存入null键null值,该集合是线程同步的JDK1.0
—-HashMap:底层是哈希表数据结构,允许使用null键null值,该集合不同步JDK1.2
—–TreeMap:底层是二叉树数据结构,线程不同步。可以用于给map集合中的键进行排序。
与Set很像。Set底层就是使用了Map集合
遍历的两种方法:https://blog.csdn.net/jiangshangchunjiezi/article/details/75268866
一、HashMap、HashTable 不同点(5点)
HashMap是最常用的Map,根据键的HashCode值存储数据,根据键可以直接获取它的值【V get(Object key)】,它具有很快的访问速度
相同点:都采用了hash法进行索引
不同点:
①轻重:HashMap是HashTable的轻量级实现(非线程安全的实现)
②线程安全:HashTable是线程安全的,HashMap不是线程安全的。
③key是否可以为空:主要区别在于HashMap允许空(null)键值(key),而HashTable不允许
import java.util.HashMap;//继承了java.util.AbstractMap
import java.util.Hashtable; //继承了java.util.Hashtable
public class HelloWorld {
public static void main(String []args) {
HashMap<Integer,String> hm=new HashMap<Integer,String>();
hm.put(1,"001");
System.out.println(hm.containsKey(1));
System.out.println(hm.containsValue("001"));
Hashtable<Integer,String> ht=new Hashtable<Integer,String>();
ht.put(null,"001");//会报空指针异常
}
}
④HashMap废除了contains方法:HashMap废弃了HashTable的contains方法去掉了,两者中都有containsValue和containsKey
⑤遍历:HashTable使用Enumeration,HashMap使用Iterator
⑥LinkedHashMap
HashMap输入输出顺序一般不一致,若要一致。LinkedHashMap是hashMap的一个子类,如果需要输出的顺序和输入的相同,那么用LinkedHashMap可以实现,它还可以按照读取顺序来排序.
二、TreeMap
一般而言,在Map中插入、删除和定位元素,HashMap是最好的选择。由于TreeMap实现了SortMap接口,能够把它保存的记录根据键排序,因此,取出来的是排序后的键值对,如果需要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。
解释:在使用自然排序时候,分为两种情况:一种是JDK定义的对象;一种是我们自己定义的对象
自然排序要求被比较的元素实现Comparable接口(实现int compareTo(T o)),否则会报异常。
①jdk定义的对象:
public final class Integer extends Numberimplements Comparable<Integer>
public int compareTo(Integer anotherInteger)//数字,从小到大
②自己定义的对象
参考TreeSet练习:https://blog.csdn.net/jiangshangchunjiezi/article/details/75212387
public class SortedTest implements Comparable<SortedTest> {
private int age;
public SortedTest(int age){
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//自定义对象,实现compareTo(T o)方法:
public int compareTo(SortedTest sortedTest) {
int num = this.age - sortedTest.getAge();
//为0时候,两者相同:
if(num==0){
return 0;
//大于0时,传入的参数小:
}else if(num>0){
return 1;
//小于0时,传入的参数大:
}else{
return -1;
}
}
}
public class TreeMapTest {
public static void main(String[] agrs){
//自然顺序比较
naturalSort();
}
//自然排序顺序:
public static void naturalSort(){
//第一种情况:Integer对象
TreeMap<Integer,String> treeMapFirst = new TreeMap<Integer, String>();
treeMapFirst.put(1,"jiaboyan");
treeMapFirst.put(6,"jiaboyan");
treeMapFirst.put(3,"jiaboyan");
treeMapFirst.put(10,"jiaboyan");
treeMapFirst.put(7,"jiaboyan");
treeMapFirst.put(13,"jiaboyan");
System.out.println(treeMapFirst.toString());
//第二种情况:SortedTest对象
TreeMap<SortedTest,String> treeMapSecond = new TreeMap<SortedTest, String>();
treeMapSecond.put(new SortedTest(10),"jiaboyan");
treeMapSecond.put(new SortedTest(1),"jiaboyan");
treeMapSecond.put(new SortedTest(13),"jiaboyan");
treeMapSecond.put(new SortedTest(4),"jiaboyan");
treeMapSecond.put(new SortedTest(0),"jiaboyan");
treeMapSecond.put(new SortedTest(9),"jiaboyan");
System.out.println(treeMapSecond.toString());
}
}
V put(K,V)
Q1:在HashTable上下文中,同步指什么
A:同步意味这在同一个时间点只能有一个线程可以修改hash表,任何线程在执行HashTable的更新操作前都需要获取对象锁,其他线程则等待锁的释放
Q2:如何实现HashMap的同步?
A:HashMap可以通过Map m=Collections.synchronizedMap(new HashMap())达到同步的效果。具体而言,该方法返回一个同步的Map,该Map封装了底层的HashMap的所有方法,使得底层的HashMap即使是多线程下,也是安全的。
// 返回由指定映射支持的同步(线程安全的)映射。
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Iterator;
import java.util.Map;
public class Woman {
public static void main(String []args) {
HashMap<Integer,String> hm=new HashMap<Integer,String>();
hm.put(1,"001");
hm.put(2,null);
hm.put(null,"003");
//第一种遍历方式
Set<Integer> s=hm.keySet();
Iterator<Integer> it=s.iterator();
while(it.hasNext()){
System.out.println(hm.get(it.next()));
}
//第二种遍历
Set<Entry<Integer,String>> me=hm.entrySet();
Iterator<Entry<Integer,String>> its=me.iterator();
while(its.hasNext())
{
Entry<Integer, String> kv=its.next();
System.out.println(kv.getKey()+"----"+kv.getValue());
}
}
}
import java.util.Enumeration;
import java.util.Hashtable;
public class HelloWorld {
public static void main(String []args) {
Hashtable<Integer,String> ht=new Hashtable<Integer,String>();
ht.put(1,"001");
ht.put(2,"002");
ht.put(3,"003");
//elements():取出所有的值
Enumeration<String> enu=ht.elements(); //enum在java中是个关键字
while(enu.hasMoreElements())
{
System.out.println(enu.nextElement());
}
}
}
二、WeakHashMap、HashMap
WeakHashMap中的key采用的是“弱引用”的方式,只要WeakHashMap中的key不再被外部引用,它就可以被垃圾回收器回收。而HashMap中的key采用的是“强引用的方式”,当HashMap中的key没有被外部引用时,只有在这个key从HashMap中删除后,才可以被垃圾回收器回收。