Stream
翻译成中文为流,是java8中处理集合的重要操作,它可以指定你对集合的操作,比如查找、过滤、映射数据等操作。用一幅图理解下什么是流。
我们要注意的是Stream不会存储元素,它不会改变原对象,只是帮我们产生一个新的流。
Stream使用的三个步骤(中间操作是不会执行处理,会在终止操作一次处理)
1.创建stream
2.中间操作,比如filter、map、sort等
3.终止操作,产生结果。
下面用一个列子来说明
public static void main(String[] args) {
//随机定义一个列表
List<Integer> integerList= Arrays.asList(1,5,6,7,9,8);
//找出列表中大于6的元素
List<Integer> list=integerList.stream() //生成流
.filter(s->s.intValue()>6) //进行filter中间操作
.collect(Collectors.toList()); //终止操作
//结果
list.forEach(s-> System.out.println(s));
}
结果
7
9
8
上面举的这个例子中的filter点开源码为 Stream filter(Predicate<? super T> predicate); 可以看到这其实是一个断言型接口。下面介绍Stream流的其他几种中间操作。
public class TestStreamAPI {
//定义一个person的列表,person的三个属性分别为 姓名、年龄、身高
List<Person> list = Arrays.asList(
new Person("张三", 21, 180),
new Person("李四", 26, 175),
new Person("王五", 23, 175),
new Person("赵六", 19, 172),
new Person("田七", 19, 178)
);
/**
* 筛选与切片: filter-接收lambda,从中排除元素
* limit-截断流,得到指定的数量
* skip(n)-跳过元素
* distinct-筛选去重 它们的顺序不同,则会产生不同的结果
*/
@Test
public void test01() {
List<Person> personList = list.stream()
.filter((s) -> s.getHeight() > 170) //找出身高大于170
.limit(2) //只要2个
.skip(1) //跳过第一个
.distinct() //去重
.collect(Collectors.toList());//终止操作
//打印结果
personList.forEach(s -> System.out.println(s.getName()));
}
/**
* 映射: map-接收lambda,将元素转换成其他形式。 flatMap-接收一个函数作为参数,将流中的每一个值都换成另一个流,然后把所有的流连成一个流
* <p>
* map和flatMap类似于 list的add和addAll方法 比如map是将 {a,a,a},{b,b,b},{c,c,c}
* 三个元素放入流中{{a,a,a},{b,b,b},{c,c,c}} flatMap是将 a,a,a,b,b,b,c,c,c放入流中然后连成一个流{a,a,a,b,b,b,c,c,c}
*/
@Test
public void test02() {
//将list中的元素的name属性收集起来
List<String> personList = list.stream().map(Person::getName).collect(Collectors.toList());
//打印结果
personList.forEach(s -> System.out.println(s));
}
/**
* 排序:
* <p>
* sort()-自热排序
* sort(Comparator com) 定制排序规则
*/
@Test
public void test03() {
List<String> strings = Arrays.asList("c", "a", "d", "f", "e", "b");
List<String> personList = strings.stream()
.sorted()
.collect(Collectors.toList());
//打印结果 a,b,c,d,e,f
personList.forEach(s -> System.out.println(s));
List<Person> people = list.stream().sorted((x, y) -> {
//按照年龄排序,如果年龄一样,按照身高排序
if (x.getAge().equals(y.getAge())) {
return x.getHeight().compareTo(y.getHeight());
} else {
return x.getAge().compareTo(y.getAge());
}
}).collect(Collectors.toList());
//打印结果
people.forEach(s -> System.out.println(s.getName()));
}
}
最后看一下几种终止操作
public class TestStreamAPI01 {
//定义一个person的列表,person的三个属性分别为 姓名、年龄、身高
List<Person> list = Arrays.asList(
new Person("张三", 21, 180),
new Person("李四", 26, 175),
new Person("王五", 23, 175),
new Person("赵六", 19, 172),
new Person("田七", 19, 178)
);
/**
* 查找与匹配
* allMatch--检查是否匹配所有元素
* anyMatch--检查是否至少匹配一个元素
* noneMatch--检查是否没有匹配所有元素
* findFirst--返回第一个元素
* count--返回流中元素的个数
* max--返回流中最大值
* min--返回流中最小值
*/
@Test
public void Test() {
//判断是否所有人年龄都为19
Boolean isAge = list.stream().allMatch(s -> s.getAge().equals(19));
System.out.println(isAge);
//判断是否有人的身高为180
Boolean isHave = list.stream().anyMatch(s -> s.getHeight().equals(180));
System.out.println(isHave);
//判断是否没有人的身高都为180
Boolean isExit = list.stream().noneMatch(s -> s.getHeight().equals(180));
System.out.println(isExit);
//找到流中第一个年龄为19的元素,关于Optional的用法后面会详情讲解
Optional<Person> personList = list.stream().filter(s -> s.getAge().equals(19)).findFirst();
System.out.println(personList.get().getName());
//计算流中元素的数量
Long number = list.stream().count();
System.out.println(number);
//找出流中身高最高的元素
Optional<Person> optionalPerson = list.stream()
.max((x, y) -> Integer.compare(x.getHeight(), y.getHeight()));
System.out.println(optionalPerson.get().getName());
//找出流中年龄最小的元素
Optional<Person> optional = list.stream()
.min((x, y) -> Integer.compare(x.getAge(), y.getAge()));
System.out.println(optional.get().getName());
}
/**
* 收集:collect--将流转换为其他形式,接收一个Collector接口的实现,用于Stream中元素做汇总的方法
*/
@Test
public void Test01() {
//将身高收集起来
List<Integer> integerList = list.stream().map(Person::getHeight)
.collect(Collectors.toList());
integerList.forEach(System.out::println);
//按照年龄去重
Set<Integer> set = list.stream().map(Person::getAge).collect(Collectors.toSet());
set.forEach(System.out::println);
//获取总数
long count = list.stream().collect(Collectors.counting());
System.out.println(count);
//获取平均身高
Double avgHeigh = list.stream().collect(Collectors.averagingDouble(s -> s.getHeight()));
System.out.println(avgHeigh);
//年龄总和
Double age = list.stream().collect(Collectors.summingDouble(s -> s.getAge()));
System.out.println(age);
//年龄最大值
Optional<Person> optional = list.stream()
.collect(Collectors.maxBy((x, y) -> Double.compare(x.getAge(), y.getAge())));
System.out.println(optional.get().getName());
//按照年龄分组
Map<Integer, List<Person>> ages = list.stream()
.collect(Collectors.groupingBy(Person::getAge));
System.out.println(ages);
//先按照年龄分组,再按照身高分组
Map<Integer, Map<Integer, List<Person>>> mapMap = list.stream().collect(
Collectors.groupingBy(Person::getAge, Collectors.groupingBy(Person::getHeight)));
System.out.println(mapMap);
//分区,将身高以175分成两部分
Map<Boolean, List<Person>> map = list.stream()
.collect(Collectors.partitioningBy(s -> s.getHeight() > 175));
System.out.println(map);
}
}