前言:
之前一直不太喜欢用 stream,理由是啥呢,之前处理集合的数据量顶多百万级别,有过一次测试,百万数据及以下处理效率不如 for 循环,千万以上 stream 处理效率高才能体现出来。为啥现在要用呢,是数据量上来了吗?那倒不是,主要是代码简洁。
一、哪些类型可以用 stream
stream 的定义就不细说,可以理解为一个管道,管道中可以设置很多过滤算法,数据经由管道就可以产出满足预设的数据。
可以使用 stream 的数据类大概三种:list、set、arr(数组)。除了 arr 使用稍微特殊点(Stream.of(arr)),其他都是 .stream() 就开始了。
二、遍历和过滤
先给个样例:
public class Main {
public static void main(String[] args) {
List<Person> list = init();
list.stream().filter(p -> {
p.setName("name:0001");
return p.getAge() > 50;
}).filter(p -> p.getAge() < 60).forEach(p -> {
System.out.println("************************");
System.out.println(p.getName());
System.out.println(p.getAge());
});
}
private static List<Person> init() {
List<Person> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
Random random = new Random();
String name = "name:" + random.nextInt(10000);
int age = random.nextInt(100);
Person person = new Person();
person.setName(name);
person.setAge(age);
list.add(person);
}
return list;
}
}
filter 可以理解是过滤条件,可以有多个;foreach 用于遍历。
三、形成集合
stream 在经过过滤计算后可以形成新的集合以方便后续使用;常用的有三个 toList、toMap、toSet:
//toSet 针对数值比较有去重效果,对象则不会生效(地址不一样)
Set<Person> set = list.stream().filter(p -> p.getAge() > 95).collect(Collectors.toSet());
//形成 list
List<Person> newList = list.stream().filter(p -> p.getAge() > 95).collect(Collectors.toList());
//形成 map;此方法没有去重效果,key 必须唯一,否则报错
Map<String, Person> map = list.stream().filter(p -> p.getAge() > 95).collect(Collectors.toMap(Person::getName, y -> y));
//数据抽取
Set<Integer> newList = list.stream().filter(p -> p.getAge() > 90).map(Person::getAge).collect(Collectors.toSet());
四、聚合计算
求和,求最大,求最小,求平均
//计算数据量
long size = list.stream().filter(p -> p.getAge() > 95).count();
//求最大最小,max:最大,min:最小;但是具体主要跟compare方法相关
Optional<Integer> optional = list.stream().max(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
});
System.out.println(optional.get());
五、类型转换
// Integer --> String
List<Integer> list1 = initList();
list1.stream().map(i -> i + "").forEach(System.out::println);
// 结构体重新赋值
set.stream().map(i -> i.setName(i.getName().toUpperCase())).forEach(person -> System.out.println(person.getName()));
六、合流
// 合流
List<Integer> list1 = initList();
List<Integer> list2 = initList();
Stream<Integer> stream1 = list1.stream();
Stream<Integer> stream2 = list2.stream();
Stream.concat(stream1, stream2).forEach(System.out::println);
七、排序
list1.stream().sorted(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
}).forEach(System.out::println);
八、补充 lambda
上述 stream 涉及了很多 lambda 表达式,这里也简单说一下。
lambda 表达式格式如下:
(params) -> expression
(params) -> statement
(params) -> { statements }
常见的例子:
// 线程
new Thread(() -> {
System.out.println("...");
}).start();
// map 遍历
map.forEach((k, v) -> {
System.out.println(k);
System.out.println(v);
});
// list 遍历
list.forEach(s -> System.out.println(s));