??xml version="1.0" encoding="utf-8" standalone="yes"?> 因此理解q堆“集合(CollectionQ类”很有必要。声明一下,以前一直都是叫它们集合c,但是好像Think In Java的作者鄙视了q个说法Q严格的说应该叫Containerc,而后看了它整整一章书以后Q觉得还是h家说的有道理?/p>
它说q个containercdQ包含了两大c,Collection和MapQ而Collection又可以分为List和Set。当然这些抽象概念都被定义成了接口?/p>
话说Q这L分类的确是严格按照类之间的承关pL说得Q但是俺总觉得很别扭Q真动手的时候,q是很难选择。当ӞAnytime and Anywhere使用ArrayListl对都能解决问题Q但q样做毕竟太农民了一炏V?/p>
所以,我自己有了一些想法。先回归到最基本最基本的数据结构的层面Q管你是Collectionq是ContainerQ反正描q的都是一堆东西吧。数据结构第一章讲了一个结构:在物理上q箋分配I间的顺序结构,叫顺序表Q希望记性是好的Q,而离散分配空间的Q应该叫做链表,最常用的就是单链表。这两个东西Q其实就是很多复杂数据结构的基础Q还记得吗,当时是讲完q些东西Q才开始讲栈、队列、二叉树、有向无向图的。所以,q个序l构是很基础的。而在JAVA中,序表对应的是List接口Q而一般顺序表是ArrayListQ有效进行随机index查找Q;而单链表是LinkedListQ有效进行插入和删除Q,两个的优劣当q都讲烂了,q里׃说了?/p>
有了q两个结构以后,JAVA׃提供Stack和Queue单独的类了,因ؓQ用户可以用上面两个c轻易的d现?/p>
那Set和Map有怎么跟Listq上关系呢? 我认为可以把它们看成是无序和单一的ListQMap只是两个有映关pȝList|了Q?/p>
Set和Map无序和单一的特性,军_了它们天大的需求就是根据关键字Q元素对象)索。soQؓ了效率,必须hash?/p>
有了HashSet和HashMap?/p>
同时Q如果非要保持住元素的顺序,有了LinkedHashSet、LinkedHashMap?/p>
假如你的需求是 psQ这两个条g其实是一回事Q因为如果是不单一的话Q你L索它q嘛?/p>
如果q而需要保持元素的序Q不要让他顺便iterationQ那选择LinkedHashSet和LinkedHashMap?/p>
假如你的需求不满以上1&2Q那你放心,List肯定能帮你解冻I你只要稍微想一下是ArrayList好还是LinkedList好?/p>
题外话: 关于HashQ务必记得要让自q元素对象override hashCode()?equles() Ҏ(gu)Q要不你直接可以z了睡?/p>
关于所有这些ContainerQ务必记得有个辅助类叫InteratorQ遍历尽量要用它?br /> 在计机中,文字是字符的集合,也就是字W串QC是因ؓ对字W串设计的不好,才那么容易溢出。而别的一些高U语aQ对于这个进行了很多的改q?/p>
~程的h׃技术方向和应用方向的不同,日常~程的内容差距很大。但是对于字W串的处理,那可是永q都避不开的工作?/p>
昨天跑步的时候,想了一下,对于字符串的操作有那么多QsearchQmatchQsplitQreplaceQ,感觉很烦杂,能不能抓住这些操作的一个基本集Q?/p>
不知道对不对Q反正想出来了一个,q个基本操作是searchQ这里的search的意思是Q在输入串中扑ֈ目标串的开始位|(start indexQ,和结束位|(end indexQ?/p>
有了q个基本集,别的操作都很好衍生出来:
局部matchQ?/strong>其实是要求search操作臛_q回一个start index?/p>
全matchQ?/strong>其实要求search操作的至返回一个start indexQƈ且start index要ؓӞend index要ؓ输入串的全长?/p>
splitQ?/strong>其实是search操作之后Q把前一个end index和当前的start index之间的字W串截出来而已?/p>
replaceQ?/strong>其实是search操作之后Q把start index和end index之间的字W串换成另外的而已?/p>
所以,归根到底Q都是一个search操作的拓展Ş了。这么一惻I感觉清晰多了?/p>
q么一来,API对search的能力支持的好坏和效率高低是衡量字符串操作功能的标准Q当Ӟ如果有直接支持matchQsplitQreplace操作的话更好了?/p>
java对字W串search的支持,最基本的就是下面的String的indexOfҎ(gu)Q?/p>
int indexOf(String str) q里我想说的是,很多时候我们所谓要search的目标串Q根本就不是固定单一的,而是变化多样的。如果只有一两种情况Q最多用两次上面的方法呗。但是有些情冉|q乎不可能罗列的Q例如,我们讲的代表email的字W串Q我们不可能遍历它吧?/p>
所以,需要一U能够通用表达字符串格式的语言。这是Regular ExpressionQreQ?/p>
假如上面Ҏ(gu)indexOf的str参数能支持re做ؓ参数的话Q那对于q种多样的search也可以用上面的方法了?/p>
可惜QindexOf不支持re作ؓ参数?br /> Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q?gt;> 全match操作Q?br />boolean matches(String regex) 全replace操作Q?br />String replaceAll(String regex, String replacement)
首个replace操作Q?br />
String replaceFirst(String regex, String replacement) 全split操作Q?br />String[] split(String regex) <<Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q?/p>
可惜啊,可惜Q可惜java的Stringc里面没有可以支持re的searchҎ(gu)Q那如果要用re来searchQ只好用java中专门的recd?/p>
java中的recd主要׃个类Q一个叫PatternQ顾名思义Q代表re的类。一个叫Matcherc,反映当前match状况的类Q如存放了当前search到的位置Q匹配的字符串等{信息)?/p>
一般在构造中Q“re的表辑ּ”作为参C递入Patternc,“输入串Q待qoԌ”作为参C递入MatchercR?/p>
然后使用Matchercȝ字符串searchҎ(gu)可以了。Matcher真正提供search功能的API叫find。下面列出?br />Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q?gt;>
boolean lookingAt()
boolean matches()
boolean find()
String group() <<Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q?/p>
前三个都是searchҎ(gu)Q返回成功与否。第四个是返回当前search上的字符丌Ӏ?br /> 当然QPattern和Matcher也包含直接用req行的matchQsplitQreplace操作?/p>
Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q?gt;> 全match操作Q?br />static boolean matches(String regex, CharSequence input) 全split操作Q?br />String[] split(CharSequence input) 有限制数的split操作Q?br />String[] split(CharSequence input, int limit)
全replace操作Q?br />String replaceAll(String replacement) 首个replace操作Q?br />String replaceFirst(String replacement) 动态replaceQreplacement可以Ҏ(gu)被替代的字符串变化而变化)
StringBuffer appendTail(StringBuffer sb)
<<Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q?br />
重点x对象的创建和销毁:什么时候、如何创建对象,什么时候、什么条件下应该避免创徏对象Q如何保证对象在合适的方式下被销毁,如何在销毁对象之前操作一些必ȝ清理行ؓ?/span>
如果一?/span>
client
要实例化一个对象来使用Q傻
b
都知道应该先调用cȝ构造器?/span>
new
一个对象,之后再调用相应的Ҏ(gu)。除了这个方式,
Java Effective
q徏议了另一U方法:用静态工厂方法来提供一个类的实?/u>。以下的例子不反映两者的优劣Q只是反映两者在代码实现上的不同Q优劣之后再谈:
假设׃要一个颜色ؓ黑色、长度ؓ
Hammer myHammer = new Hammer(Color.BLACK, 50);
而用静态工厂方法来实例化一个对象,如下
Hammer myHammer = Hammer.factory(Color.BLACK,50);
也可以用专门的一个工厂类来实例化
Hammer myHammer = Toolkit.factory(“Hammer? Color.BLACK,50);
单纯从上面的代码上看Q真的只有傻
b
才会选择静态工厂的Ҏ(gu)Q完全就是多此一举,直接
new
又快又爽Q搞q么ȝ做莫斯(武汉话“什么”的意思)Q?/span>
别急,别急,你急个?/span>
b
Q武汉粗话:基本是“你急个毛”的意思)Q?/span>
下面p说用静态工厂代替构造器的好处(
advantage
Q和不好处(
disadvantage
Q?/span>
W一个好处,讲你都不信,行家们认为,构造器有一个不好的地方是Q这个方法的{Q?/span>
signture
Q太固定了?/span>
构造器的名字是固定的,生个
Hammer
Q构造器的名字就?/span>
Hammer
Q……)Q唯一能变化的地方是参数Q假设我的这个锤子有两个很变态的构造需要:
1
Q第一个参数是颜色Q?/span>
Color
型)Q第二个参数是锤子头的重量(
int
型)?/span>
Hammer
Q?/span>
Color c, int kg
Q?/span>
{
//remainder omited
}
2
Q第一个参数是颜色Q?/span>
Color
型)Q第二个参数是锤子的长度Q?/span>
int
型)?/span>
Hammer
Q?/span>
Color c, int cm
Q?/span>
{
//remainder omited
}
感觉满需要了Q但是细心一看,完了Q构造器的参数列表类型重复了Q肯定编译通不q,q是面向对象构造器天生的缺陷——唯一的变化就是参敎ͼ参数都分辨不了,q的分辨不了?/span>
而另外就参数能分L的了Q构造器一多,它的参数一多,(zhn)根本就不知道每个参数是用来q什么的Q只能去查阅文档Q在(zhn)已l眼qq时候再L文档Q一个一个的对,折磨人的zR?/span>
q个时候,(zhn)就可以考虑用静态工厂方法来实例化对象了。因为静态工厂方法有一个最单的特点是Q他有可以变化的Ҏ(gu)名(构造器的名字变不了Q。用名字的不同来代表不同的构造需要,q么单的普通的特点在这里就是它相对于构造器?/span>
advantage
?/span>
如上面的锤子的例子可以这P
1
Q?/span>
Hammer.produceByWeight (Color c, int kg){
//remainder omited
}
2
Q?/span>
Hammer.produceByHeight (Color c, int cm){
//remainder omited
}
q是不是一目了然多了。嗯Q我是这栯为的?/span>
W二个好处,“静态工厂方法不需要每ơ都真的d例化一个对象”——其实这也是另一些优化方法的前提?/span>
构造器的每?/span>
invoke
必定会生一个新的对象,而静态工厂方法经q一定的控制Q完全可以不用每?/span>
invoke
都生成一个新的对象?/span>
Z么不每次都生成一个对象的原因׃必说了,因ؓ原因太明显。这个原因就是ؓ什么要“共享”对象的原因?/span>
下面讲讲通常使用的两U共享具体策略,也就是具体方法了Q?/span>
1
Q单例模式的需要,一旦需要某个对象有单例的需要,必定对于q类对象的构造只能用静态工厂方法了?/span>
2
Q?/span>
flyweight
模式和不变(
immutable
Q?/span>
模式的需要,q两个模式很多时候都说一起用的Q一旦一些对象我们认为是不变的,那自然就x来重用,也就说共享,?/span>
flyweight
是用来重用q些粒度对象的?/span>
?/span>
Boolean.valueOf (boolean)
Ҏ(gu)Q?/span>
Boolean a = Boolean.valueOf (100);
Boolean b = Boolean.valueOf (100);
aQ?span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">
l论Q?/p>
1Q往Container中放的对象是无序且单一的;
2Q经常要索?br />用HashSet或HashMap吧?/p>
关于一些老的Stack、Vector、HashTableQ听说以后不要用了哦。收到啦Q!
]]>
Returns the index within this string of the first occurrence of the specified substring.
soQ以下就介绍java api中可以用re作ؓ参数的字W串操作Ҏ(gu)Q参C的regex是reQ?/p>
StringcȝQ?/p>
Tells whether or not this string matches the given regular expression.
Replaces each substring of this string that matches the given regular expression with the given replacement.
Replaces the first substring of this string that matches the given regular expression with the given replacement.
Splits this string around matches of the given regular expression.
有限制数的split操作Q?br />String[] split(String regex, int limit)
Splits this string around matches of the given regular expression.
Matchercsearch操作相关的方法:
Attempts to match the input sequence, starting at the beginning, against the pattern.
Attempts to match the entire input sequence against the pattern.
Attempts to find the next subsequence of the input sequence that matches the pattern.
Returns the input subsequence matched by the previous match.
okQ至此。用re的search操作也有眉目了?/p>
Pattercd的字W串操作Ҏ(gu)
Compiles the given regular expression and attempts to match the given input against it.
Splits the given input sequence around matches of this pattern.
Splits the given input sequence around matches of this pattern.
Matchercd的字W串操作Ҏ(gu)
Replaces every subsequence of the input sequence that matches the pattern with the given replacement string.
Replaces the first subsequence of the input sequence that matches the pattern with the given replacement string.
Matcher appendReplacement(StringBuffer sb, String replacement)
Implements a non-terminal append-and-replace step.
Implements a terminal append-and-replace step.
ȝQ?br />当必M用re的时候,search操作p用到PatternQMatcherQ当然动态的replace操作也要用到q两个类。而别的matchQreplaceQsplit操作Q可以用patternQMatcherQ当然也可以直接使用StringQ推荐还是用回咱们的String吧?br />
注:以上都是看jdk1.4以上的文得出的l论Q以前版本不能用不负责Q?/p>
试用静态工厂方法代替构造器
q些对象都是不变的,?/span> valueOf 的控制就是用?/span> flyweight Ҏ(gu)?/span>
q种一个状态(如上面一个数字)对应的对象只有一个还有一个好处,是可以直接通过比较“引用”来判断他们是否
equel
Q这里的
equel
是逻辑相等的意思)Q以前需?/span>
a.equels(b)
Q而一旦用?/span>
flyweight
模式和不变(
immutable
Q?/span>
模式”后Q避免了产生多余的相同对象,?/span>
a==b
可以达?/span>
a.equels(b)
的目的了。这样当然优化了
performance
?/span>
W三个好处,其实是工厂Ҏ(gu)的核心好处——我把它UCؓ“抽象类型构造器”。它可以为我们提供一个抽象类型的实例Q同时必要的隐藏了抽象类型的具体l构。这?/span>
new
怎么都达不到的?/span>
q种模式的好处其实就是面向对象的最核心的好处,抽象和具体可以分,一旦抽象定义好了,具体的东西可以慢慢的变化Q慢慢的拓展——开闭原则?/span>
?/span>
Collections Framework API
Q都是描q集合类型的接口Q也是对于客户端来看,只有
Collection
q个c要认识Q而实际上Q实现这个接口的
Collection
是多U多L。如果要让用户都知道q些具体实现?/span>
Collection
Q就增加了复杂度?/span>
q时Q通过一个静态工厂方法,可以隐藏各U?/span>
Collection
的具体实玎ͼ而让
Client
只用返回的
Collection
对象可以了?/span>
q里q可以加上一些权限控Ӟ如这些实现只要对于工厂来讲是可以讉K的,不用?/span>
public
的,而他们只要通过
public
的工厂就可以提供l用戗非常有利于代码的安全?/span>
静态工厂方法的W一个缺点就是:使用静态工厂方法创建的cȝ构造器l常都是非公共或?/span>
protected
的?/span>
q样Q以后这些类没有办法被l承了。不q也有h_不用l承q
composition
呗。也是!呵呵?/span>
静态工厂方法的W二个缺Ҏ(gu)Q在
jdk
文里,q些静态工厂方法很难跟别的静态方法相区别?/span>
而文中Q构造器是很Ҏ(gu)看到的?/span>
Z一定程度解册个问题,我们可以用一些比较特别的名字来给q类静态工厂方法来命名。最常用的有Q?/span>
valueOf
—?/span>
用来攑֛跟参数“相同值”的对象?/span>
getInstance
—?/span>
q回一个对象的实例。单例模式中Q就是返回单例对象?/span>
ȝQ静态工厂方法和构造器都有各自的特炏V最好在考虑用构造器之前能先考虑一下静态工厂方法,往往Q后者更有用一炏V如果权衡了以后也看不出那个好用一些,那就用构造器Q毕竟简单本分多了?/span>