什么是IOQ?/strong>
一提vIOlh的感觉就比较复杂Q不q确实也挺复杂的Q,可能是学C的时候吓怕了Q呵c不q,理一下思\q是比较清晰的。在Java里,IO说白了就?font color="#ff0000">对读、写的一U抽?/strong>。没有什么其他的复杂的东ѝ至于读什么、写什么,那就看你惌什么、想写什么,p己控制了?/p>
M么?写什么?
看看下面q个图会清楚很多Q只用看InputStreampQOutputStream一PQ?/p>
大家可以看一下直接承InputStream的几个类ByteArrayInputStream、FileInputStream、StringBufferInputStream(PipedInputSteram和SequenceInputStream一般不?。呵呵,看看q几个类?font color="#ff0000">构造函?/strong>明了了。第一个是把byte数字作ؓIO源读取byte数组里的东西Q第二个是把文g作ؓIO源读取文仉的东西,W三个是把String作ؓIO源读取String里面的东ѝ这么看q几个IO实在单。说白了是从byte数组、文件、String按字节读取Ş?.... 一句简单的话说QIO体系W一U承的几个c?strong>解决了从哪儿L者写到哪儿的问题
怎么读?怎么写?
试想一下,现在要读一个几癑օ的文Ӟ怎么dQ是一下子把整个文仉d内存慢慢分析呢,q是每次dM个字节逐个分析呢?昄两个都不好,于是我们惛_了缓册Ӏ所以IO体系上有了BufferedInputStream。再想一下,现在你想写一个?.1415926”到文g里怎么写?M能自己把q个数的二进制Ş式写出来Q{成byte数组写到文g里吧。即便写q去了读的时候怎么dQ谁知道你写q去的是数字而不是其他字W呢Q?/p>
于是针对怎么读Java IO体系上出C一个分支FilerInoutStream(FilterOutputStream)。承了q个cȝ几个cd自对怎么诅R写提供了不同的支持。Buffered提供了缓ԌLineNumber提供了对不同cd数据的读写?/p>
q是一句话QIO体系的第二l承解决了怎么诅R怎么?/strong>?/p>
以不变应万变
说IO不能不说他的DecoratorQ装饎ͼ模式。此模式在这里的应用实很经典!从上面两D늚分析看来Java的IO是分成两部分从哪儿读(写)和怎么读(写)。想想看Q一个数据源可能需要不同的d方式、而不同的数据源都可能需要同一直读写方式。于是这里的l合方式是一U乘U。n个数据源×n中处理方式?n-1)处理方式Q有时候可能涉及多U处理方式的叠加Q=n^3。想想看Q要是一个一个写q不写死......
从IO体系的根看,InputStream(OutputStream)提供了最Ҏ的readQwriteQ方法。各子类提供各自实现。而得益于DecoratorQ各子类q可以把自己的处理方式加到read(write)的前后,形成一U处理方式的叠加?/p>
JDKq部分的代码比较单。看一下就大概知道Decorator怎么实现的了?/p>
q根溯源
我们见到的IO最大的应用一个应该是数据的持久化QFileinputStream(FileOutputStream)已经实现了。而另一个则是网l传输。之前我很想知道IO是怎么在网l上实现传输的?q有上面说的几个IO都不存在“阻塞”问题,那么IO的阻塞实在哪儿生的呢? 找了半天对于扑ֈ了下面一句:
class SocketInputStream extends FileInputStream
再追下去找C一些nativeҎQ这个就出我能力之外了。不q可以猜惻I底层的东西应该就是C的一些文件读写了。这个就不是Java的问题:Q目前暂时这么认为,以后或许能发C些新的东ѝ?/p>
Ҏ蒂固的痛——国际化
~码问题不仅是Java头痛的问题,也是每一个用Java的h都头痛的问题。IO也不例外。InputStreamQOutputStreamQ体p都是针对字节(byteQ进行读写的。这L问题是字节可能是没有意义的,只有几个字节联合转换才能得到有意义的东西。所以如果是字节q要再次q行~解码才能得到我们想要的东西?/p>
Z避免q个ȝQ字W体p?Read、Write)产生了。他们可以对进行编解码Q这样可以直接得到用h要的东西。两个体pd大体上都是对应的。再多的东西我也没有深入了解了:Q?/p>
q有一个要提的是,什么时候用字符、什么时候用字节呢?TIJ里有交代Q?font color="#ff0000">大部分时候用字符Q字W不行的时候再考虑字节。呵呵,挺简l的?/p>
日新月异
nio应该是老掉牙的东西了。不q对于我q个初始IO的h来说q有待进一步了解。目前知道两点:上面的IO体系的底层都已经用nio重写了,所以速度上应该差不多。这L来,一般情况下用上面的IO是没问题的。再一个是Qnio最大的优势在于他的“非dIO”,不过q个东东是用在网l编E的。一般也用不上?/p>
再新的东西就是前两天看到的一?a href="../../jobs/archive/2006/11/21/82409.html">blogQ关于aioQ异步IOQ的大家有兴可以自q看?/p>
大家先来看段代码?
List list = new ArrayList();
list.add("exception");
for (Iterator iter = list.iterator(); iter.hasNext();) {
String element = (String) iter.next();
list.remove(element);
}
q段代码q行时会抛出异常Q呵呵,不知道大家发现问题没Q?/p>
q段代码会抛出:java.util.ConcurrentModificationException。也是所谓的?a >Fail Fast”。用了很久Java了,才发现这么一个异常,着实郁闷了一?.....啥都不说了,拿v书来Q重新来q?/p>
Z么要IteratorQ?/strong>
下面是一个Collection的M图:
上面代码涉及了一个经典的涉及模式Q?a >Iterator模式。既然涉及了q个模式Q就要问问ؓ什么这里要用这个模式。查了一下书Q有q么几句描述Iterator的:q代逻辑没有改变Q但是需要将一U聚集变换成另一U聚集。因Z同的聚集遍历接口不同Q所以需要修改客L代码。这几句话没错,而且我们用Iterator都有如文章开头示例的标准方式Q然而仔l想来却q有炚w题?/p>
假设Iterator是ؓ了实现遍历方ѝ可是,我们几个常用的聚集(如:ArrayListQLinkedListQSet{)都已l间接实CCollection接口。而大家应该注意到Collection接口中有?font color="#ff0000">size()Ҏ。这Ll果是,Ҏ有实CCollection的聚集而言Q我们都可以通过for (int i = 0; i < list.size(); i++)q样的Ş式实现遍历。而且QJDK1.5q可以通过foreach的Ş式大大简化代码量。所以,q样xIteratorZ实现遍历的方便而引入,昄不成立?/p>
接着找找。我们可以注意到QSet和List两个大类中一个很大的区别是:List提供getҎQ?a >Set没有提供getҎ。这Ll果是Setcd能往集合中放Q却不能从集合中取(从一般的常识来说Q这样做q是合理的)。呵呵,所以这里我只能猜想Iterator是不是是Z讉KSet中元素而设计的了?/p>
仅仅猜想Q不知道大家有没有什么更好的xQ?/p>
讨论Q?/strong>
跟朋友讨Z一下,for(int i = 0; i < list.size(); i++)对应遍历LinkedList来说是致命的。对ArrayList是O(n)Q而LinkedList则是O(n^2)Q这L效率是不能让人接受的?/font>
如上所_那么foreach的引入应该是在编译层ơ对两种不同数据l构q行了不同处理。而且成ؓ了Iterator的替代?/font>
不过q里又引Z另一个问题—?/font>
Iterator模式如何用在其他地方Q作ZU设计模式Iterator应该有更q的使用价值吧?/font>
Iterator的缺?/strong>
q里没有贬低Iterator的意思,只是实在看不Z有啥好处......
集合
能力有限Q感觉了解还是太,也没太多好说的,只是有些区别应该注意一下?/p>