數值流,顧名思義就是專門用來操做基礎數據類型的流,那它的做用是什麼呢?先看下面的代碼。這段代碼是獲取集合每一個對象的num
字段的值,而後求所和。得出的結果是15,看上去沒有問題,可是要注意的是流在進行求和操做的時候從對象中取出來的是基本類型,會進行裝箱操做變成Integer
類型再進行求和,性能會有所降低,而數值流就是專門對基本類型數據進行操做的。數組
public class DataStream { public static void main(String[] args){ List<Num> list = new ArrayList<Num>(); Num num1 = new Num(1); Num num2 = new Num(2); Num num3 = new Num(3); Num num4 = new Num(4); Num num5 = new Num(5); list.add(num1); list.add(num2); list.add(num3); list.add(num4); list.add(num5); System.out.println(list.stream().map(Num::getNum).reduce(Integer::sum)); } } class Num{ private int num; public Num(int num) { this.num = num; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } }
1.想要使用數值流其實很簡單,只須要調用Stream.mapToInt()
方法就能夠得到一個數值流了,咱們會發現數值流有更多的封裝好的計算方法,更加方便咱們對數值的計算。dom
System.out.println(list.stream().mapToInt(Num::getNum).count()); System.out.println(list.stream().mapToInt(Num::getNum).sum()); System.out.println(list.stream().mapToInt(Num::getNum).max()); System.out.println(list.stream().mapToInt(Num::getNum).min()); System.out.println(list.stream().mapToInt(Num::getNum).average());
運行結果:函數
5 15 OptionalInt[5] OptionalInt[1] OptionalDouble[3.0]
2.須要注意的是max
、min
和average
方法若是在流爲空的時候獲取不到值會返回空的Optional
對象,而count
和sum
方法則是返回0。性能
運行結果:this
0 0 OptionalInt.empty OptionalInt.empty OptionalDouble.empty
3.有時候咱們可能會想將數值流轉換回原來的流,咱們能夠調用boxed()
方法。code
public static void changeStream(){ int[] arr = new int[]{1,2,3,4,5}; IntStream intStream = Arrays.stream(arr); Stream<Integer> stream = intStream.boxed(); }
4.上面咱們介紹的是IntStream
,它專門用來處理int
類型的數值,除此以外還有DoubleStream
和LongStream
,它們分別處理double
和long
類型的數值,只要調用mapToDouble
和mapToLong
方法便可得到對應的數值流,使用方法也是IntStream
大同小異,這裏就不作詳細介紹了。對象
以前的文章中咱們一直都是直接調用集合的stream
方法來獲取一個流,其實獲取流的方式有不少種。get
直接使用值初始化流it
public static void valueStream(){ Stream<String> stream = Stream.of("Hello", "World "); stream.map(String::toUpperCase).forEach(System.out::println); }
使用Arrays.stream()
靜態方法建立流,這個方法接受一個數組io
public static void arrayStream(){ String[] strs = new String[]{"Hello","World"}; Arrays.stream(strs).map(String::toUpperCase).forEach(System.out::println); }
從文件中讀取獲取流,每一行就是流中的一個元素
public static void fileStream(){ try { Stream<String> text = Files.lines(Paths.get("C:\\Users\\Half\\Desktop\\test.txt"),Charset.defaultCharset()); text.forEach(System.out::println); } catch (IOException e) { e.printStackTrace(); } }
用函數生成無限流,分別調用Stream.iterate()
和Stream.generate()
方法便可,二者不一樣之處在於Stream.iterate()
方法沒生成一個值都要依賴於前一個值,適合生成連續的數值,而Stream.generate()
則每一個值都是獨立生成的,相互之間沒有關聯。要注意的是由於是無限流,因此會一直生成元素,因此必需要調用limit()
方法來限制生成的個數,不然代碼會一直運行下。
Stream.iterate()
接受兩個參數,分別是起始值和後續值的生成代碼,例以下面這個方法就是從0開始,依次加10
public static void iterateStream(){ Stream.iterate(0, num -> num+10).limit(5).forEach(System.out::println); }
運行結果:
0 10 20 30 40
Stream.generate()
接受一個參數,生成數值的代碼
public static void generateStream(){ Stream.generate(Math::random).limit(5).forEach(System.out::println); }
運行結果:
0.9538068193407456 0.5113995186169759 0.20525086606957266 0.2974528805300197 0.019653649898021208
這篇文章介紹了數值流和構建流的方式,流的應用能夠很靈活,後續還會介紹流的用法。