Java Stream简介, 流的基本概念.
在Java or .net編程中,? 我們經(jīng)常見(jiàn)到"stream" 這個(gè)字眼.
我們大概知道這是個(gè)流的意思, 如果看完本文的話, 應(yīng)該會(huì)有1個(gè)大概的概念.
一, Java中什么是Stream(流)
1.1 1段輸出文件內(nèi)容到屏幕的代碼
假如我們有個(gè)需求, 利用java寫(xiě)1個(gè)程序, 將1個(gè)硬盤(pán)上的文件(/home/gateman/tmp/build.xml)內(nèi)容輸出到屏幕上.
Java的代碼如下:
import java.io.*;public class Stream1{public static void f() throws IOException{FileReader fr = new FileReader("/home/gateman/tmp/build.xml");int ch; //not charch = fr.read(); //throws IOEXCEPTIONwhile(ch > -1){ //if ch = -1, means got the end of the fileSystem.out.printf("%c",(char)ch);ch = fr.read(); //throws IOEXCEPTION}} }上面的代碼很簡(jiǎn)單,
1.首先我們見(jiàn)到代碼定義了1個(gè) FileReader 對(duì)象fr.? 它的某個(gè)成員指向了我們要讀的文件build.xml.
2.然后多次執(zhí)行 fr.read()方法, 每執(zhí)行一次, 將fr.read()打返回結(jié)果輸出到屏幕. 直到fr.read()的返回值是-1.
這里包括我也許有人會(huì)想, 為什么要 read 那么多次啊, 干脆寫(xiě)1個(gè)強(qiáng)大的read()方法把文件內(nèi)容都讀過(guò)來(lái)不就完了嗎?
這就是涉及了流的概念.
1.2 搬水的例子
我們來(lái)舉個(gè)例子讓大家更加容易理解
問(wèn)題1:
假如有兩個(gè)杯子, 其中1個(gè)有水, 另1個(gè)沒(méi)有水,? 它們的位置都不能移動(dòng).
請(qǐng)問(wèn)有什么方法將有水杯子了的水搬去另1個(gè)杯子?
答案很多種,? 只需要1個(gè)碗, 把水倒進(jìn)碗里, 然后把碗的水倒進(jìn)另1個(gè)杯子里就ok了.
將這個(gè)思路應(yīng)用到1.1 的例子, 就相當(dāng)于1個(gè)強(qiáng)大的Read()方法把整個(gè)文件都讀完了.?
為什么這樣說(shuō)?
1. 我們可以把有水的杯子看做1個(gè)文件, 水相當(dāng)于文件的內(nèi)容.
2. 沒(méi)水的杯子相當(dāng)于屏幕. 我們就是需要把文件的內(nèi)容輸出到屏幕
3. 中間的碗相當(dāng)于內(nèi)存,? 把有水的杯子的水倒進(jìn)碗就是一次過(guò)把文件所有內(nèi)容讀入內(nèi)存啊.
4. 最后把碗的水倒進(jìn)另1個(gè)杯子, 相當(dāng)于把內(nèi)存里的內(nèi)容輸出到屏幕.
如下圖:
問(wèn)題貌似解決了, 但是隨著這個(gè)問(wèn)題的規(guī)模的擴(kuò)大, 這個(gè)方法就不可行了.
例如需要搬運(yùn)的不是一杯水,?? 而是把整個(gè)個(gè)池塘的水運(yùn)到另一個(gè)池塘.
用碗來(lái)搬就不符合實(shí)際啊.
有人回說(shuō), 我一碗一晚的搬總會(huì)搬完?
問(wèn)題是, 那個(gè)碗(內(nèi)存)還可以其他東西,? 如果整個(gè)內(nèi)存都用于搬運(yùn)數(shù)據(jù), 那么就導(dǎo)致程序在搬運(yùn)數(shù)據(jù)的時(shí)間里占用大部分操作系統(tǒng)的內(nèi)存.? 留給其他程序的內(nèi)存就很少了!
1.3 搬水的例子的另1個(gè)解決方法: 管道
假如我們的內(nèi)存(碗)容量很少, 但是要搬運(yùn)整個(gè)池塘怎么辦呢?
其實(shí)我們就可以用一條水管接通兩個(gè)池塘.
管道上有1個(gè)按鈕, 每按1次那個(gè)按鈕, 就允許一點(diǎn)水通過(guò)管道.
如下圖:
結(jié)合1.1 的java代碼例子
實(shí)際上我們已經(jīng)明白,? FileReader fr 這個(gè)對(duì)象就相當(dāng)于1條管道, 這個(gè)管道有1個(gè)按鈕 fr.read(), 每執(zhí)行1次, 就有一點(diǎn)水流(1個(gè)字符) 讀到內(nèi)存(注意是內(nèi)存, 而不是屏幕)!
1.4 本文開(kāi)始1.1節(jié)java代碼的分析
我們?cè)倏椿?.1 的代碼.
當(dāng)執(zhí)行碗上面的代碼后,
實(shí)際上建立了1條 從文件到內(nèi)存的一條數(shù)據(jù)管道.
但是這時(shí)只是搭建好了1個(gè)管道, 并沒(méi)有數(shù)據(jù)傳輸
這個(gè)方法需要處理IOException
這個(gè)也不難理解, 每讀到1個(gè)字符, 就把這個(gè)字符輸出到屏幕上, 直到讀完整個(gè)文件.
如下圖:
而第一句建立的對(duì)象 FileReader fr實(shí)際上就是1個(gè)文件讀字符流
流(Stream)實(shí)際上就是從數(shù)據(jù)文件到程序的一條管道.
至于數(shù)據(jù)怎么從程序輸出到屏幕, 這個(gè)并不是流的范疇.
1.5 Java Stream流的定義
看完上面例子的話, 流的定義就很容易看懂了.
Stream是java的1個(gè)類(lèi), 這個(gè)類(lèi)專(zhuān)門(mén)用于程序和外部設(shè)備的輸入輸出(IO). 基本上所有流都在 java.io這個(gè)包中.
實(shí)際上Stream就是數(shù)據(jù)在程序和外部設(shè)備的單向管道, 流的各種方法相當(dāng)于管道上的各種按鈕.??
所謂的外部設(shè)備可以包括硬盤(pán)文件, 網(wǎng)絡(luò)設(shè)備, 另個(gè)程序等. 也就是當(dāng)前程序之外的數(shù)據(jù)設(shè)備.
二, 為什么需要Stream(流).
看懂了上面的的例子, Stream存在的意義也很簡(jiǎn)單.
1. 數(shù)據(jù)的傳輸量很大.
2. 內(nèi)存有限.
3. 帶寬有限.
而Stream可以1點(diǎn)1點(diǎn)地逐步傳輸所有數(shù)據(jù), 這就是Stream存在的根本意義.
想想我們是怎樣下載1個(gè)大文件的, 下載軟件(例如x雷)并不會(huì)占用你內(nèi)存很大的空間, 而只是在內(nèi)存劃分1個(gè)緩沖區(qū), 一點(diǎn)一點(diǎn)地下載到自己的內(nèi)存(緩沖區(qū)滿了再寫(xiě)到硬盤(pán)), 這也是流的1個(gè)例子啊.
三,流的重要特性.
3.1 流是java里的一個(gè)類(lèi)
也就是將流就是類(lèi)的一種, 但反過(guò)來(lái)類(lèi)不是流
3.2 數(shù)據(jù)并不會(huì)在流里自動(dòng)傳輸
而是需要執(zhí)行流的方法, 一次傳輸一定量的數(shù)據(jù).
3.3 1個(gè)流對(duì)象只有1個(gè)傳輸方向
也就是說(shuō)流是單向的, 數(shù)據(jù)要么從程序到設(shè)備(OutputStream), 要么從設(shè)備到程序(InputStream).
下一編 介紹留的分類(lèi)以及java中的四大基本流.
總結(jié)
以上是生活随笔為你收集整理的Java Stream简介, 流的基本概念.的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Java里的数组介绍
- 下一篇: Java Stream(流)的分类, 四