- 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:返回无序流,也可能返回本身