##关于hashmap和hashtable的区别
1,hashmap是单线程的,线程不安全,而hashtable是多线程的,而且在源码的方法中都加入了synchronized进行关于线程安全方面的处理,但是这个hash table是1.5以前的,现在都是使用hashmap来替换hashmap,当然在这个过程中发现现在有一个更好的类接口方法,那就是ConcurrentHashMap。它提供了hashmap的基本功能,但是在实际的场景还需要考虑其他因素,所以这个在下一篇博客会好好的剖析下。为何不使用hashtable那是因为hashtable效率底下,在并发的情况下很容易产生可能会进入阻塞或轮询状态。降低了用户体验。
2,hashmap null 值(key和value都可以)。Hashtable不允许 null 值(key 和 value 都不可以)。这个在应用场景中的关于数据的填写会产生一些不确定的因素,毕竟这个需要根据用户的需求的添加,而不是强制的去让用户去选择,这也是选择使用不同框架的原因吧。
1 2 3 4 5
| Hashtable table = new Hashtable(); table.put("a-key", "a-value"); table.put("b-key", "b-value"); table.put("c-key", "c-value"); table.put("c-key",null);
|
结果:
Exception in thread “main” java.lang.NullPointerException
at java.util.Hashtable.put(Hashtable.java:399)
at com.darkmi.sandbox.HashtableTest.main(HashtableTest.java:20)
3.遍历方式的不同,hashtable是使用的是Enumeration,而hashmap使用iterator遍历方式
4。hashmap在多线程的状态下遍历不稳定,有时候会打印出异常,有时候出现正常值的情况,在网上看了一个源码,是因为
一般我们声明HashMap时,使用的都是默认的构造方法:HashMap,看了代码你会发现,它还有其它的构造方法:HashMap(int initialCapacity, float loadFactor),其中参数initialCapacity为初始容 量,loadFactor为加载因子,而之前我们看到的threshold = (int)(capacity * loadFactor); 如果在默认情况下,一个HashMap的容量为16,加载因子为0.75,那么阀值就是12,所以在往HashMap中put的值到达12时,它将自动扩 容两倍,如果两个线程同时遇到HashMap的大小达到12的倍数时,就很有可能会出现在将oldTable转移到newTable的过程中遇到问题,从 而导致最终的HashMap的值存储异常。,而所给出的代码是在两个线程的作用下才需要这样,所以对于一些基本的数据都是用的是hashmap而如果要跨平台,分布式的开发应用需要使用ConcurrentHashMap来保证线程的安全,防止丢失用户数据,这个是作为我们开发行业提供确切的服务所需要的严谨的态度,而且要把可控性把握在自己手里,而不是在机器。下面是我学习这个方面的一个例子吧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package hashmaptest; import java.util.HashMap; public class MainClass { public static final HashMap<String, String> firstHashMap=new HashMap<String, String>(); public static void main(String[] args) throws InterruptedException { Thread t1=new Thread(){ public void run(){ for(int i=0;i<25;i++){ firstHashMap.put(String.valueOf(i),String.valueOf(i)); } } }; Thread t2=new Thread(){ public void run(){ for(int j=0;j<25;j++){ firstHashMap.put(String.valueOf(j),String.valueOf(j)); } } }; t1.start(); t2.start(); Thread.currentThread().sleep(1000); for(int l=0;l<50;l++){ if(!String.valueOf(l).equals(firstHashMap.get(String.valueOf(l)))){ System.err.println(String.valueOf(l)+":"+firstHashMap.get(String.valueOf(l))); } } } }
|
结果输出的有时是稳定的:
25:null
有时确实1:null
2:null
25:null
这就体现了hashmap在多线程的不稳定性,所以这个hashmap在单线程的情况下使用,多线程使用ConcurrentHashMap,为何使用这个类呢,如果只是仅仅为了线程安全而放弃更好的性能这是不值得的,使用了锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。这样就像是一个线程池那样灵活的去使用线程,提高了效率,还能够保证了安全,在以后的设计中我应该更偏向于安全和用户体验。
##总结
通过一个问题去深入的去看代码,和看下别人的博客怎么去解决问题,这也许就是发现问题,提出问题,想办法去解决问题,付出的不仅仅是时间,还有就是思考的过程,也许现在还是在别人的思想中转,,但是这就是让我以后少走这个错误,让我的开发更贴近于用户的需要,提供更好的服务,服务源于技术,而服务对象源于用户。技术改变世界,还改变自我,加油