﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-少年阿宾-随笔分类-guava</title><link>http://www.blogjava.net/stevenjohn/category/54771.html</link><description>那些青春的岁月</description><language>zh-cn</language><lastBuildDate>Wed, 01 Apr 2015 13:04:38 GMT</lastBuildDate><pubDate>Wed, 01 Apr 2015 13:04:38 GMT</pubDate><ttl>60</ttl><item><title>ImmutableMap源码解析</title><link>http://www.blogjava.net/stevenjohn/archive/2015/01/08/422140.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Thu, 08 Jan 2015 11:47:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2015/01/08/422140.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/422140.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2015/01/08/422140.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/422140.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/422140.html</trackback:ping><description><![CDATA[为什么ImmutableMap是不可变集合，是线程安全的？<br />首先介绍一下基本概念，什么事immutable<p><strong>何为Immutable对象？</strong></p><p>简单地说，如果一个对象实例不能被更改就是一个Immutable的对象，Java SDK提供的大量值对象，比如String等都是Immutable的对象。</p><p><strong>如何使对象Immutable？</strong></p><p>按照Effective Java的说明，需要满足下面几条规则：</p><ul><li>保证类不能被继承 - 为了避免其继承的类进行mutable的操作</li><li>移调所有setter/update等修改对象实例的操作</li><li>保证所有的field是private和final的</li></ul><br />不可变对象（immutable objects），后面文章我将使用immutable objects来代替不可变对象！ <p> 那么什么是immutable objects?什么又是mutable Objects呢？ </p><p>immutable Objects就是那些一旦被创建，它们的状态就不能被改变的Objects，每次对他们的改变都是产生了新的immutable的对象，而mutable Objects就是那些创建后，状态可以被改变的Objects. </p><p>举个例子：String和StringBuilder，String是immutable的，每次对于String对象的修改都将产生一个新的String对象，而原来的对象保持不变，而StringBuilder是mutable，因为每次对于它的对象的修改都作用于该对象本身，并没有产生新的对象。 </p><p> 但有的时候String的immutable特性也会引起安全问题，这就是<span style="color: #e53333;"><strong><a href="http://my.oschina.net/jasonultimate/blog/166968" target="_blank" rel="nofollow">密码应该存放在字符数组中而不是String中</a></strong></span>的原因！ </p><p>immutable objects 比传统的mutable对象在多线程应用中更具有优势，它不仅能够保证对象的状态不被改变，而且还可以不使用锁机制就能被其他线程共享。 </p><p> 实际上JDK本身就自带了一些immutable类，比如String，Integer以及其他包装类。为什么说String是immutable的呢？比如：java.lang.String 的trim，uppercase,substring等方法，它们返回的都是新的String对象，而并不是直接修改原来的对象。 </p><p><strong><span style="color: #e53333;">如何在Java中写出Immutable的类？</span></strong> </p><p> 要写出这样的类，需要遵循以下几个原则： </p><p><span style="color: #9933e5;">1）immutable对象的状态在创建之后就不能发生改变，任何对它的改变都应该产生一个新的对象。</span> </p><p><span style="color: #9933e5;">2）Immutable类的所有的属性都应该是final的。</span> </p><p><span style="color: #9933e5;">3）对象必须被正确的创建，比如：对象引用在对象创建过程中不能泄露(leak)。</span> </p><p><span style="color: #9933e5;">4）对象应该是final的，以此来限制子类继承父类，以避免子类改变了父类的immutable特性。</span> </p><p><span style="color: #9933e5;">5）如果类中包含mutable类对象，那么返回给客户端的时候，返回该对象的一个拷贝，而不是该对象本身（该条可以归为第一条中的一个特例）</span> </p><p> 当然不完全遵守上面的原则也能够创建immutable的类，比如String的hashcode就不是final的，但它能保证每次调用它的值都是一致的，无论你多少次计算这个值，它都是一致的，因为这些值的是通过计算final的属性得来的！ </p><br />有时候你要实现的immutable类中可能包含mutable的类，比如java.util.Date,尽管你将其设置成了final的，但是它的值还是可以被修改的，为了避免这个问题，我们建议返回给用户该对象的一个拷贝，这也是Java的最佳实践之一。<br /><span style="color: #4c33e5;">使用Immutable类的好处：</span><br /><span style="color: #4c33e5;">1）Immutable对象是线程安全的，可以不用被synchronize就在并发环境中共享</span> <p><span style="color: #4c33e5;">2）Immutable对象简化了程序开发，因为它无需使用额外的锁机制就可以在线程间共享</span> </p><p><span style="color: #4c33e5;">3）Immutable对象提高了程序的性能，因为它减少了synchroinzed的使用</span> </p><p><span style="color: #4c33e5;">4）Immutable对象是可以被重复使用的，你可以将它们缓存起来重复使用，就像字符串字面量和整型数字一样。你可以使用静态工厂方法来提供类似于valueOf（）这样的方法，它可以从缓存中返回一个已经存在的Immutable对象，而不是重新创建一个。</span> </p><p>immutable也有一个缺点就是会制造大量垃圾，由于他们不能被重用而且对于它们的使用就是&#8221;用&#8220;然后&#8221;扔&#8220;，字符串就是一个典型的例子，它会创造很多的垃圾，给垃圾收集带来很大的麻烦。当然这只是个极端的例子，合理的使用immutable对象会创造很大的价值。 </p><br /><br />Guava提供的ImmutableMap是一个支持多线程环境下面的安全的Map，同时效率也是很高的Key-Value集合，为什么他就是安全的呢。<br />&nbsp; &nbsp; 先看下面例子：<br />&nbsp; &nbsp; &nbsp; &nbsp; ImmutableMap.Builder&lt;String, Object&gt; request = ImmutableMap.builder();<br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;request.put("one","1");<br />&nbsp; &nbsp; &nbsp; &nbsp; request.put("two","2");<br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;request.put("three","3");<br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;Map&lt;String, Object&gt; map = request.build();<br />&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 让我们首先从Builder&lt;T,T&gt;入手进行分析<br /><br />&nbsp;public static class Builder&lt;K, V&gt; {<br />&nbsp;&nbsp;&nbsp; TerminalEntry&lt;K, V&gt;[] entries;<br />&nbsp;&nbsp;&nbsp; int size;<br /><br /><br />&nbsp;public ImmutableMap&lt;K, V&gt; build() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (size) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 0:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return of();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 1:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return of(entries[0].getKey(), entries[0].getValue());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new RegularImmutableMap&lt;K, V&gt;(size, entries);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }<br /><br />}<br /><br />上面的<br />&nbsp;ImmutableMap.Builder&lt;String, Object&gt; request = ImmutableMap.builder();<br />这个实例创建的时候，只是创建了一个空的对象。<br />那么实际效用的是build() <br />&nbsp; @SuppressWarnings("unchecked")<br />&nbsp;&nbsp;&nbsp; Builder(int initialCapacity) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.entries = new TerminalEntry[initialCapacity];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.size = 0;<br />&nbsp;&nbsp;&nbsp; }<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><br /><br /><img src ="http://www.blogjava.net/stevenjohn/aggbug/422140.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2015-01-08 19:47 <a href="http://www.blogjava.net/stevenjohn/archive/2015/01/08/422140.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>