个人感觉Stream是作为JDK8最出色的成果,没有之一。Stream的存在是对于过去集合类(Collection)的增强,它提供大量的API对于集合对象的聚合操作,这些API使用起来十分便利,并且使代码的可读性大大提高。
首先,我们一起来感受下Stream的能力
例1:在一个ArrayList中添加如下角色:
乔峰、段誉、虚竹、天山童姥、王语嫣、张无忌、张三丰、张飞
需求:1.得到所有姓张的;
2.得到所有名字是2个字的;
3.遍历打印所有名字
public class DemoStream1 {
public static void main(String[] args) {
ArrayList<String> nameList = new ArrayList<>();
Collections.addAll(nameList, "乔峰", "段誉", "虚竹", "天山童姥", "王语嫣", "张无忌", "张三丰", "张飞");
// 1.得到所有姓张的;
ArrayList<String> zhangList = new ArrayList<>();
for (String s : nameList) {
if(s.contains("张")){
zhangList.add(s);
}
}
System.out.println("zhangList = " + zhangList.toString());
List<String> zhangList1 = nameList.stream().filter(name->name.contains("张")).collect(Collectors.toList());
System.out.println("zhangList1 = " + zhangList1.toString());
System.out.println("-----------------------");
// 2.得到所有名字是2个字的;
ArrayList<String> twoList = new ArrayList<>();
for (String s : nameList) {
if(s.length() == 2){
twoList.add(s);
}
}
System.out.println("twoList = " + twoList.toString());
List<String> twoList2 = nameList.stream().filter(name->name.length() == 2).collect(Collectors.toList());
System.out.println("twoList2 = " + twoList2.toString());
System.out.println("-----------------------");
// 3.遍历打印所有名字
for (String s : nameList) {
System.out.println(s);
}
System.out.println("-----------------");
nameList.stream().forEach(System.out::println);
}
}
==运行结果==
zhangList = [张无忌, 张三丰, 张飞]
zhangList1 = [张无忌, 张三丰, 张飞]
-----------------------
twoList = [乔峰, 段誉, 虚竹, 张飞]
twoList2 = [乔峰, 段誉, 虚竹, 张飞]
-----------------------
乔峰
段誉
虚竹
天山童姥
王语嫣
张无忌
张三丰
张飞
-----------------
乔峰
段誉
虚竹
天山童姥
王语嫣
张无忌
张三丰
张飞
通过以上代码,我们可以轻易地发现。过去对于集合类的操作过于繁琐;而通过Steam的API,我们可以是代码更加简洁,如果使用流的并发模式,当数据量爆炸的时候,还可以提高执行效率。
public class DemoStream2 {
public static void main(String[] args) {
Stream<String> stream1 = Stream.of("张三", "李四", "王五");
stream1.forEach(System.out::println);
System.out.println("--------------");
stream1.forEach(System.out::println);
}
}
==运行结果==
张三
李四
王五
Exception in thread "main" --------------
java.lang.IllegalStateException: stream has already been operated upon or closed
at java.util.stream.AbstractPipeline.sourceStageSpliterator(AbstractPipeline.java:279)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at com.onlymark.demo1.jdk8.DemoStream2.main(DemoStream2.java:21)
// Collection.stream() 和 Collection.parrellelStream()
List<String> list = new ArrayList<>();
Stream<String> stream3 = list.stream();
// Arrays.stream(T array)
int[] intArr = new int[5];
IntStream stream = Arrays.stream(intArr);
// Stream.of()
Stream<String> stream5 = Stream.of("张三", "李四", "王五");
这部分内容大部分借鉴了Java 8 stream的详细用法这篇Blog的内容,仰望大神。
方法名 | 描述 | 返回值类型 | 方法类型 |
---|---|---|---|
count | 统计 | long | 终结 |
forEach | 逐个处理 | void | 终结 |
filter | 过滤 | Stream | 管道 |
limit | 取前N个 | Stream | 管道 |
skip | 跳过前N个 | Stream | 管道 |
distinct | 去重 | Stream | 管道 |
map | 映射 | Stream | 管道 |
concat | 组合 | Stream | 管道 |
public class DemoStream3 {
public static void main(String[] args) {
Stream<Integer> stream1 = Stream.of(1, 2, 3, 3, 4, 5, 6, 7, 11, 13, 14, 14, 14, 20);
stream1.filter(i->i>4) //5, 6, 7, 11, 13, 14, 14, 14, 20
.limit(8) //5, 6, 7, 11, 13, 14, 14, 14
.skip(2) //7, 11, 13, 14, 14, 14
.distinct() //7, 11, 13, 14
.forEach(System.out::println);
}
}
==运行结果==
7
11
13
14
在这里插入代码片
public class DemoStream4 {
public static void main(String[] args) {
List<String> strList = Arrays.asList("h,e,l,l,o", "w,o,r,l,d");
//map
strList.stream()
.map(str->str.replace(",", ""))// "hello", "world"
.forEach(System.out::println);
System.out.println("---------------");
//flatmap
strList.stream()
.flatMap(str->{
String[] split = str.split(",");
Stream<String> stream = Arrays.stream(split);
return stream;
})
.forEach(System.out::println);
}
}
==运行结果==
hello
world
---------------
h
e
l
l
o
w
o
r
l
d
public class DemoStream5 {
public static void main(String[] args) {
Stream<Integer> integerStream = Stream.of(2, 1, 5, 4, 7);
//sorted
integerStream.sorted().forEach(System.out::println);
List<Person> personList = new ArrayList<>();
Person p1 = new Person("小明", 12);
Person p2 = new Person("小红", 11);
Person p3 = new Person("小刚", 13);
Collections.addAll(personList, p1, p2, p3);
//sorted(Comparator com)
personList.stream().sorted((person1, person2)->{
return person1.getAge() - person2.getAge();
}).forEach(p-> System.out.println(p.toString()));
}
}
==运行结果==
1
2
4
5
7
Person{name='小红', age=11}
Person{name='小明', age=12}
Person{name='小刚', age=13}
public class DemoStream6 {
public static void main(String[] args) {
List<Person> personList = new ArrayList<>();
Person p1 = new Person("小明", 12);
Person p2 = new Person("小红", 11);
Person p3 = new Person("小刚", 13);
Collections.addAll(personList, p1, p2, p3);
//peek
personList.stream()
.peek(person -> person.setAge(100))
.forEach(person -> System.out.println(person.toString()));
}
}
==运行结果==
Person{name='小明', age=100}
Person{name='小红', age=100}
Person{name='小刚', age=100}
public class DemoStream7 {
public static void main(String[] args) {
List<Integer> integerList = Arrays.asList(1, 2, 3, 5, 6, 7, 9, 11, 13, 20, 99, 100);
//allMatch
boolean b1 = integerList.stream().allMatch(integer -> integer > 99);
System.out.println("b1 = " + b1);
//noneMatch
boolean b2 = integerList.stream().noneMatch(integer -> integer > 100);
System.out.println("b2 = " + b2);
//anyMatch
boolean b3 = integerList.stream().anyMatch(integer -> integer == 11);
System.out.println("b3 = " + b3);
//findFirst
Integer i1 = integerList.stream().findFirst().get();
System.out.println("i1 = " + i1);
//findAny
Integer i2 = integerList.stream().findAny().get();
System.out.println("i2 = " + i2);
//count
long count1 = integerList.stream().count();
System.out.println("count1 = " + count1);
//max
Integer max = integerList.stream().max(Integer::compareTo).get();
System.out.println("max = " + max);
//min
Integer min = integerList.stream().min(Integer::compareTo).get();
System.out.println("min = " + min);
}
}
==运行结果==
b1 = false
b2 = true
b3 = true
i1 = 1
i2 = 1
count1 = 12
max = 100
min = 1
public class DemoStream8 {
public static void main(String[] args) {
List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer v = intList.stream().reduce((x1, x2) -> x1 + x2).get();
System.out.println(v); // 55
System.out.println("-----------");
Integer v1 = intList.stream().reduce(10, (x1, x2) -> x1 + x2);
System.out.println(v1); //65
}
}
==运行结果==
55
-----------
65
public class DemoStream9 {
public static void main(String[] args) {
List<Person> personList = new ArrayList<>();
Person p1 = new Person("小明", 12);
Person p2 = new Person("小红", 11);
Person p3 = new Person("小刚", 13);
Person p4 = new Person("小王", 12);
Collections.addAll(personList, p1, p2, p3, p4);
//封装list
List<String> nameList = personList.stream().map(person -> person.getName()).collect(Collectors.toList());
System.out.println("nameList = " + nameList);
//封装set
Set<String> nameSet = personList.stream().map(person -> person.getName()).collect(Collectors.toSet());
System.out.println("nameSet = " + nameSet);
//封装成map
Map<String, Integer> personMap = personList.stream().collect(Collectors.toMap(Person::getName, Person::getAge));
System.out.println("personMap = " + personMap);
//字符串分隔符连接
String nameJoinStr = personList.stream().map(Person::getName).collect(Collectors.joining("$"));
System.out.println("nameJoinStr = " + nameJoinStr);
//聚合操作
//总数
Long personNum = personList.stream().collect(Collectors.counting());
System.out.println("personNum = " + personNum);
//求所有人的年龄和1
Integer ageSum = personList.stream().map(Person::getAge).collect(Collectors.summingInt(age -> age));
System.out.println("ageSum = " + ageSum);
//求所有人的年龄和2
Integer ageSum1 = personList.stream().collect(Collectors.summingInt(Person::getAge));
System.out.println("ageSum1 = " + ageSum1);
//求所有人的年龄和3
Integer ageSum2 = personList.stream().map(Person::getAge).reduce((age1, age2) -> age1 + age2).get();
System.out.println("ageSum2 = " + ageSum2);
//求所有人的年龄平均数
Double ageAvg = personList.stream().collect(Collectors.averagingDouble(Person::getAge));
System.out.println("ageAvg = " + ageAvg);
//分组
Map<Integer, List<Person>> personAgeGroup = personList.stream().collect(Collectors.groupingBy(Person::getAge));
System.out.println("personAgeGroup = " + personAgeGroup);
//多层分组
Map<Integer, Map<String, List<Person>>> agenameGroup = personList.stream().collect(Collectors.groupingBy(Person::getAge, Collectors.groupingBy(Person::getName)));
System.out.println("agenameGroup = " + agenameGroup);
//分区
Map<Boolean, List<Person>> collect = personList.stream().collect(Collectors.partitioningBy(person -> person.getAge() > 12));
System.out.println("collect = " + collect);
}
}
==运行结果==
Connected to the target VM, address: '127.0.0.1:56217', transport: 'socket'
nameList = [小明, 小红, 小刚, 小王]
nameSet = [小刚, 小明, 小王, 小红]
personMap = {小刚=13, 小明=12, 小王=12, 小红=11}
nameJoinStr = 小明$小红$小刚$小王
personNum = 4
ageSum = 48
ageSum1 = 48
ageSum2 = 48
ageAvg = 12.0
personAgeGroup = {11=[Person{name='小红', age=11}], 12=[Person{name='小明', age=12}, Person{name='小王', age=12}], 13=[Person{name='小刚', age=13}]}
agenameGroup = {11={小红=[Person{name='小红', age=11}]}, 12={小明=[Person{name='小明', age=12}], 小王=[Person{name='小王', age=12}]}, 13={小刚=[Person{name='小刚', age=13}]}}
Disconnected from the target VM, address: '127.0.0.1:56217', transport: 'socket'
collect = {false=[Person{name='小明', age=12}, Person{name='小红', age=11}, Person{name='小王', age=12}], true=[Person{name='小刚', age=13}]}
Java 8 中的 Streams API 详解
Java 8 stream的详细用法