JDK8中首次引入Stream的操作(不是IO的stream),可以让你声明式的方式处理数据。
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
简单来说,Stream包装了数据源,让我们更方便和更快速的批量处理数据。
- Stream不存储数据,也不是一种数据结构,也不修改底层的数据源
创建Stream
常见的创建Stream操作有3种。
1 从数组中创建流,Stream.of
2 从集合中直接获取Stream,Java 8中,Collection接口默认实现了stream方法
3 利用StreamBuilder创建流
@Test
public void createStream() {
// 1. 使用Stream.of创建流
Stream stream = Stream.of("apple", "banana", "fruit");
// 2. Java8之后,所有的Collection集合可以使用stream方法获取流
Stream listGetStream = Arrays.asList("apple", "banana", "fruit").stream();
// 3. 使用Stream.Buidler创建流
Stream.Builder
Stream操作
基本操作(forEach,findFirst, flatMap,peek)
@Data
static class Person {
int age;
String name;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
@Test
public void streamForEach() {
List personList = Arrays.asList(
new Person("aihe", 23),
new Person("wuxian", 30),
new Person("fengxi", 29)
);
personList.stream().forEach(p -> {
p.setAge(p.getAge() + 1);
});
for (Person person : personList) {
System.out.println(person.getAge());
}
}
/**
* map操作会产生新的Stream
* collect将Stream中的处理后的数据进行收集
*/
@Test
public void streamMap() {
List personList = Arrays.asList(
new Person("aihe", 23),
new Person("wuxian", 30),
new Person("fengxi", 29)
);
List names = personList.stream()
.map(person -> person.getName())
.collect(Collectors.toList());
System.out.println(names);
}
@Test
public void streamFilter() {
List personList = Arrays.asList(
new Person("aihe", 23),
new Person("wuxian", 30),
new Person("fengxi", 29)
);
List person = personList.stream()
.filter(p -> p.getAge() > 25)
.filter(p -> p.getName().startsWith("w"))
.collect(Collectors.toList());
System.out.println(person);
}
/**
* findFirst。默认返回Optional的值
*/
@Test
public void streamFindFirst() {
Stream stream = Stream.of("1", "2");
String first = stream
.findFirst()
.orElse(null);
System.out.println(first);
}
@Test
public void streamToArray(){
String[] strings = Stream.of("1", "2", "3").toArray(String[]::new);
System.out.println(strings);
}
/**
* 将复杂的数据结构如List等进行平铺操作。如
* [[1,2],[3,4]] => [1,2,3,4]
*/
@Test
public void streamFlatMap(){
Stream> stream = Stream.of(
Arrays.asList("1", "2"),
Arrays.asList("3", "4")
);
List collect = stream.flatMap(Collection::stream)
.collect(Collectors.toList());
System.out.println(collect);
}
/**
* 上面演示了forEach,foreach是最终的一步操作,返回void类型。
* peek操作操作与forEach相同,但是可以多次操作,中间的数据加工阶段
*/
@Test
public void streamPeek(){
List personList = Arrays.asList(
new Person("aihe", 23),
new Person("wuxian", 30),
new Person("fengxi", 29)
);
List collect = personList.stream()
.peek(person -> person.setAge(person.getAge() + 1))
.peek(person -> person.setName(person.getName().concat(" Hangzhou")))
.collect(Collectors.toList());
System.out.println(collect);
}
Collect操作
@Test
public void testCollect(){
List stringList = Arrays.asList("1", "2", "3");
String collect = stringList.stream().collect(Collectors.joining(","));
System.out.println(collect);
Set setCollect = stringList.stream().collect(Collectors.toSet());
System.out.println(setCollect);
ArrayList arrayListCollect = stringList.stream().collect(Collectors.toCollection(ArrayList::new));
System.out.println(arrayListCollect);
IntSummaryStatistics intSummaryStatistics = stringList.stream().collect(Collectors.summarizingInt(s -> Integer.parseInt(s)));
System.out.println(intSummaryStatistics.getSum());
}
数学操作(排序,最大,最小值)
@Test
public void streamMathOp(){
Stream integerStream = Stream.of(1, 3, 5, 7, 9, 2, 4, 6, 8);
List integerList = integerStream.sorted((x, y) -> y.compareTo(x)).collect(Collectors.toList());
System.out.println(integerList);
Optional max = integerList.stream().max((x, y) -> x - y);
System.out.println(max.get());
integerList.add(1);
integerList.add(2);
List distinctList = integerList.stream().distinct().collect(Collectors.toList());
System.out.println(distinctList);
}
逻辑操作
/**
* 逻辑操作
*/
@Test
public void streamLogic(){
List list = Arrays.asList(1, 2, 3);
boolean allMatch = list.stream().allMatch(i -> i > 2);
boolean anyMatch = list.stream().anyMatch(i -> i > 2);
boolean noMatch = list.stream().noneMatch(i -> i > 2);
System.out.println(allMatch);
System.out.println(anyMatch);
System.out.println(noMatch);
}
GroupBy & Mapping
@Test
public void streamGroupBy() {
List list = Arrays.asList("1", "2", "aihe", "1", "aihe", "3");
Map> collect = list.stream()
.collect(
Collectors.groupingBy(s -> s, Collectors.mapping(s -> s, Collectors.toList()))
);
System.out.println(collect);
}
无限Stream
/**
* 每一个新的元素,调用generate中的Supplier方法进行生成。
*/
@Test
public void testGenerate(){
List collect = Stream.generate(Math::random)
.limit(5)
.collect(Collectors.toList());
System.out.println(collect);
}
/**
* iterate需要一个种子数,然后根据种子元素生成下一个元素
*/
@Test
public void testIterate(){
Stream integerStream = Stream.iterate(2, integer -> integer * 2);
List list = integerStream.limit(5)
.collect(Collectors.toList());
System.out.println(list);
}
File
@Test
public void streamFileRead() throws IOException {
Stream lines = Files.lines(Paths.get("D:\\code\\daily\\doll-machine\\src\\main\\resources\\application.properties"));
List stringList = lines.collect(Collectors.toList());
for (String s : stringList) {
System.out.println(s);
}
}
@Test
public void streamFileWrite() throws IOException {
BufferedWriter bufferedWriter = Files.newBufferedWriter(Paths.get("test.txt"), StandardOpenOption.CREATE,StandardOpenOption.WRITE);
PrintWriter pw = new PrintWriter(bufferedWriter);
Stream.of("aihe","wuxian","fengxi")
.forEach(pw::println);
pw.close();
}
最后
这里主要给出了Java 8Stream的一些操作案例,目前比较懒,没有写太多注释,复制下来运行的时候查看效果即可知道具体是用来做什么的。
参考:
https://stackify.com/streams-guide-java-8/
https://www.baeldung.com/java-8-streams
https://martinfowler.com/articles/collection-pipeline/