- Stream
JAVA8新增了一個抽象,稱之爲流,可以以一種聲明的方式來處理數據。一般用來處理集合,我們可以認爲是一種高級集合。這個方式是將數據集合看做是一種流,在管道中傳輸,經過中間各種操作後,最終得到前面處理的結果。 - 流的特點
- 只能遍歷一次
- 採用內部迭代的方式(這個需要和傳統集合的遍歷方式作對比,外部迭代是指需要我們手寫代碼進行處理。而內部迭代只需要告訴他我們需要什麼,具體處理則交給流的內部)。
- 流的操作
- 創建一個流
- 中間操作
- 最終操作
接下來我們就從以上三個步驟來學習JAVA8的新特性-流。
- 創建一個流
流的創建一般來源於集合,因此我們可以通過以下方式來創建流:- 通過集合中提供的
Stream()
順序流或者ParallelStream()
並行流。 - 通過
Arrays
中的stream()
獲取數組流。 Stream
中的靜態of()
方法。- 創建無線流。
- 創建空流
- 通過集合中提供的
public static void createStream(){
// 通過集合提供的Stream()順序流或者ParallelStream()並行流。
List list = new ArrayList();
list.add("555");
list.add("333");
list.add("888");
Stream s = list.stream();
Stream s2 = list.parallelStream();
System.out.println("---------------");
s.forEach(System.out::println);
System.out.println("---------------");
s2.forEach(System.out::println);
System.out.println("---------------");
//通過Arrays中的stream()獲取數組流。
String[] strings = {"1","2"};
Stream arrayStreams = Arrays.stream(strings);
System.out.println("---------------");
arrayStreams.forEach(System.out::println);
System.out.println("---------------");
//Stream中的靜態of()方法。
Stream streamOf = Stream.of(1,2,3,4,5,6);
System.out.println("---------------");
streamOf.forEach(System.out::println);
System.out.println("---------------");
//創建無線流
Stream.generate(()->"stream"+new Random().nextInt()).limit(10).forEach(System.out::println);
//創建空流
Stream stream = Stream.empty();
System.out.println("---------------");
stream.forEach(System.out::println);
}
- 流的操作:包括中間操作、終端操作、延遲執行和短路操作
中間操作:
map:映射每個元素到對對應的結果。
public static void map(){
List<Integer> numbers = Arrays.asList(1,2, 3,3, 2, 6, 6);
numbers.stream().map(i->{
if(i>3){
return i;
}else {
return i*3;
}
}).forEach(System.out::println);
System.out.println("--------------------");
String[] strings = new String[]{"111","2222","333"};
List re = Arrays.asList(strings).stream().map(x->x+"_JACK").collect(toList());
Arrays.asList(strings).stream().map(x->x+"_JACK").forEach(System.out::println);
}
flatMap:對流扁平化處理,其實就是對集合中的元素內容進行處理
public static void flatMap(){
List<Integer> numbers = Arrays.asList(1,2, 3,3, 2, 6, 6);
numbers.stream().flatMap(y->Arrays.asList(y).stream()).distinct()
.collect(toList())
.forEach(System.out::println);
System.out.println("--------------------");
List<String> strings = Arrays.asList("1,2","8,99","342,24,32");
strings.stream().flatMap(x->Arrays.stream(x.split(",")))
.collect(toList()).
forEach(System.out::println);
System.out.println("--------------------");
String[] words = new String[]{"Hello","World"};
List<String> a = Arrays.stream(words)
.map(word -> word.split(""))
.flatMap(Arrays::stream)
.distinct()
.collect(toList());
a.forEach(System.out::print);
}
輸出內容:
1
2
3
6
--------------------
1
2
8
99
342
24
32
--------------------
HeloWrd
mapToInt:也是對集合中的每個元素進行操作:(相同類型的操作還有mapToLong、mapToDouble等)
public static void mapToInt(){
List<String> numbers = Arrays.asList("I","can","study","JAVA");
long a = numbers.stream().mapToInt(x->x.length()).sum();
System.out.println("mapToInt>>>"+a);
a = numbers.stream().mapToInt(m->{
System.out.println("-------"+m);
System.out.println(">>>>>"+m.indexOf("a"));
return m.indexOf("a");
}).sum();
System.out.println("mapToInt>>>"+a);
List<Integer> numbersint = Arrays.asList(1,2,3,3,2);
double d = numbersint.stream().mapToInt(x->x*2).average().getAsDouble();
System.out.println("mapToInt d>>>"+d);
//通過boxed轉化爲流對象
numbersint.stream().mapToInt(x->x*2).boxed().forEach(System.out::println);
}
輸出結果:
mapToInt>>>13
-------I
>>>>>-1
-------can
>>>>>1
-------study
>>>>>-1
-------JAVA
>>>>>-1
mapToInt>>>-2
mapToInt d>>>4.4
2
4
6
6
4
filter:過濾元素,返回滿足filter裏面函數表達式條件的集合中的每個元素。
public static void filter(){
List<String> strings = Arrays.asList("I","can","study","JAVA");
strings.stream().filter(x->x.indexOf("a")<0).forEach(System.out::println);
System.out.println("----------------");
(strings.stream().filter(y->y.length()>3).collect(toList())).stream().forEach(System.out::println);
System.out.println("----------------");
}
輸出內容
I
study
JAVA
----------------
study
JAVA
distinct:去重
public static void distinct(){
List<String> strings = Arrays.asList("I","can","I","JAVA");
strings.stream().distinct().forEach(System.out::println);
List<Integer> numbers = Arrays.asList(1,2,3,2,4,5,5,5);
System.out.println("----------------");
numbers.stream().mapToInt(x->x*2).distinct().boxed().forEach(System.out::println);
}
輸出結果:
I
can
JAVA
----------------
2
4
6
8
10
sorted:對流進行排序
public static void sorted(){
//new Random().ints().limit(10).sorted().boxed().forEach(System.out::println);
List<String> strings = Arrays.asList("I","can","study","jAVA");
System.out.println("----------------");
strings.stream().sorted().forEach(System.out::println);
System.out.println("----------------");
List<Integer> numbers = Arrays.asList(1,2,3,2,4,5,5,5);
numbers.stream().distinct().sorted(Comparator.naturalOrder()).forEach(System.out::println);
System.out.println("----------------");
numbers.stream().distinct().sorted(Comparator.reverseOrder()).forEach(System.out::println);
System.out.println("----------------");
List<Person> list = new ArrayList<>();
list.add(new Person(1,"張三",20));
list.add(new Person(2,"李四",18));
list.add(new Person(3,"王五",30));
list.stream().sorted(Comparator.comparing(Person::getAge)).forEach(System.out::println);
System.out.println("----------------");
list.stream().sorted(Comparator.comparing(Person::getName)).collect(toList()).forEach(System.out::println);
}
輸出結果:
I
can
jAVA
study
----------------
1
2
3
4
5
----------------
5
4
3
2
1
----------------
Person{id=2, name='李四', age=18}
Person{id=1, name='張三', age=20}
Person{id=3, name='王五', age=30}
----------------
Person{id=1, name='張三', age=20}
Person{id=2, name='李四', age=18}
Person{id=3, name='王五', age=30}
peek:對集合中的對象的進行操作
public static void peek(){
List<Person> list = new ArrayList<>();
list.add(new Person(1,"張三",20,1000));
list.add(new Person(2,"李四",18,500));
list.add(new Person(3,"王五",30,3000));
list.stream().peek(x->{
if (x.getAge()>30){
x.setSalary(x.getSalary()*3);
}else {
x.setSalary(x.getSalary()*1.5f);
}
}).forEach(System.out::println);
}
輸出結果:
Person{id=1, name='張三', age=20, salary=1500.0}
Person{id=2, name='李四', age=18, salary=750.0}
Person{id=3, name='王五', age=30, salary=4500.0}
limit:獲取指定數量的流
public static void limit(){
List<String> strings = Arrays.asList("I","can","study","jAVA");
strings.stream().limit(2).forEach(System.out::println);
System.out.println("----------------");
new Random().ints().limit(10).boxed().sorted().limit(3).forEach(System.out::println);
}
輸出結果:
I
can
----------------
-1950400451
-1226075663
-1043223600
skip:跳過前N個對象
public static void skip(){
Stream stream = new Random().ints().limit(10).sorted().boxed();
List list = (List) stream.collect(toList());
list.stream().forEach(x->System.out.println("隨機10個數>>>>"+x));
System.out.println("----------------");
list.stream().skip(5).forEach(y->System.out.println("隨機10個數 的後五個數>>>>"+y));
}
輸出結果:
隨機10個數>>>>-1199923688
隨機10個數>>>>-587487676
隨機10個數>>>>-467571709
隨機10個數>>>>-364617507
隨機10個數>>>>-276125709
隨機10個數>>>>315251677
隨機10個數>>>>557156463
隨機10個數>>>>595423289
隨機10個數>>>>1639981209
隨機10個數>>>>2039405344
----------------
隨機10個數 的後五個數>>>>315251677
隨機10個數 的後五個數>>>>557156463
隨機10個數 的後五個數>>>>595423289
隨機10個數 的後五個數>>>>1639981209
隨機10個數 的後五個數>>>>2039405344
以下操作是在Stream
的接口BaseStream
中:
parallel:併發處理,並行流就是把內容分成多個數據塊,使用不同的線程分別處理每個數據塊的流。
sequential:串行流
unordered:返回無序流,也可能返回本身