一、Stream流介绍
Streanm流式一个集合元素模型,与数据结构无关,不会存储元素包括内存地址。操作起来有点类似SQL语句一样的操作,如filter, map, reduce, find, match, sorted等。但是效率比普通的for循环要慢。
二、filter
filter方法用于通过设置的条件过滤出元素。
ArrayList<String> dataList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
dataList.add(i+"");
}
List<String> collect = dataList.stream().filter(s -> Integer.parseInt(s) > 10).collect(Collectors.toList());
这里使用filter将集合元素转化为数字后比较比10大的元素。
三、collect
collect含义是确定返回的是类型,可Map、List或者String等。
ArrayList<String> dataList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
dataList.add(i+"");
}
// 这里将每个元素用,拼接成字符串返回
List<String> collect = dataList.stream().collect(Collectors.joining(", "));
// 这里将元素放入List里
List<String> collect = dataList.stream().collect(Collectors.toList());
//这里将元素放入一个map里,toMap(key,value , 当key相等时要后者还是前者)
Map<String, Integer> map = dataList.stream().collect(Collectors.toMap(String::toString, Integer::parseInt , (v1,v2)->v1));
四、聚合(count/max/min)
count用于统计元素的个数。
ArrayList<String> dataList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
dataList.add(i+"");
}
//统计大于10的
long count = dataList.stream().filter(s -> Integer.parseInt(s) > 10).count();
//取年龄最大的person对象
Person person = personList.stream().max(Comparator.comparing(Person::getAge)).get();
五、map/peek/flatMap
map方法用于主要映射元素对应结果
ArrayList<String> dataList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
dataList.add(i+"");
}
List<Integer> collect = dataList.stream().map(s -> Integer.parseInt(s)*2).collect(Collectors.toList());
System.out.println(collect);
//或者
List<Integer> collect = dataList.stream().map(Integer::parseInt).collect(Collectors.toList());
peek:与map最大的区别是peek没返回值,但是会执行对应的方法
List<Integer> intList = Arrays.asList(1, 44, 56, 7, 8);
List<Integer> list = intList.stream().peek(s -> s += 100).collect(Collectors.toList());
//打印出来,发现两个集合元素值都没改变,同时原始值
System.out.println(intList);
System.out.println(list);
//将Person对象中的salary属性都添加1000元。但是原始的personList也将值给改变了
List<Person> collect = personList.stream()
.peek(per -> per.setSalary(per.getSalary() + 1000))
.collect(Collectors.toList());
flatMap:接收一个函数,将流中的值换成另外一个流
List<String> list = Arrays.asList("m,k,l,a", "1,3,5,7");
List<String> listNew = list.stream().flatMap(s -> {
// 将每个元素转换成一个stream
String[] split = s.split(",");
return Arrays.stream(split);
}).collect(Collectors.toList());
六、limit
方法用于获取指定数量的流
List<String> collect = dataList.stream().limit(10).collect(Collectors.toList());
七、sorted 排序
sorted 方法用于对流进行排序,默认是升序,如果想降序则传参Comparator.reverseOrder()。 也可根据指定条件进行排序
- 升序
ArrayList<String> dataList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
dataList.add(i+"");
}
// 升序
List<String> collect = dataList.stream().sorted().collect(Collectors.toList());
- 降序
ArrayList<String> dataList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
dataList.add(i+"");
}
// 升序
List<String> collect = dataList.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
- 复杂
ArrayList<User> dataList = new ArrayList<>();
for (int i = 0; i < 30; i++) {
User user = new User();
user.setAge(i);
user.setName("小"+i);
dataList.add(user);
}
//这里是要筛选出大于18或等于18岁的用户,并且按照年龄进行降序。
List<User> collect = dataList.stream().filter(item -> item.getAge() >= 18)
.sorted(Comparator.comparing(User::getAge).reversed())
.collect(Collectors.toList());
System.out.println(collect);
//按照年龄排序,如果年龄相等按照首字母排序
dataList.stream().sorted((x, y) -> {
if ( x.getAge()==y.getAge()){
return y.getName().charAt(0) - x.getName().charAt(0);
}
return x.getAge()-y.getAge();
}).forEach(System.out::println);
八、统计(summaryStatistics/count/averaging)
ArrayList<User> dataList = new ArrayList<>();
for (int i = 0; i < 30; i++) {
User user = new User();
user.setAge(i);
user.setName("小"+i);
dataList.add(user);
}
IntSummaryStatistics stats = dataList.stream().mapToInt(User::getAge).summaryStatistics();
System.out.println("年龄最大为 : " + stats.getMax());
System.out.println("年龄最小为 : " + stats.getMin());
System.out.println("所有年龄之和 : " + stats.getSum());
System.out.println("平均数 : " + stats.getAverage());
List<Person> personList = new ArrayList<Person>();
personList.add(new Person("Tom", 8900, 23, "male", "New York"));
personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
// 求平均工资
Double collect = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
// 求工资之和
Integer sum = personList.stream().collect(Collectors.summingInt(Person::getSalary));
mapToInt(x -> x) 这里主要放表达式,代表着需要计算的元素。
九、规约(reduce)
//取出对象的年龄然后相加。
Integer data = personList.stream().map(Person::getAge).reduce(Integer::sum).get();
System.out.println(data);
//相加
List<Integer> data = Arrays.asList(1, 45, 67, 787, 232);
Integer integer = data.stream().reduce(Integer::sum).get();
//相乘
List<Integer> data = Arrays.asList(1, 45, 67, 787, 232);
Integer integer = data.stream().reduce((x, y) -> x * y).get();
十、分组(partitioningBy/groupingBy)
List<Person> personList = new ArrayList<Person>();
personList.add(new Person("Tom", 8900, "male", "New York"));
personList.add(new Person("Jack", 7000, "male", "Washington"));
personList.add(new Person("Lily", 7800, "female", "Washington"));
personList.add(new Person("Anni", 8200, "female", "New York"));
personList.add(new Person("Owen", 9500, "male", "New York"));
personList.add(new Person("Alisa", 7900, "female", "New York"));
//按工资是否大于8000来放行分类
Map<Boolean, List<Person>> part = personList.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 8000));
//按照首字母进行分组
Map<Character, List<Person>> collect = personList.stream().collect(Collectors.groupingBy(x -> x.getName().charAt(0)));
// 将员工先按性别分组,再按地区分组
Map<String, Map<String, List<Person>>> group2 = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea)));
十一、提取/组合
流也可以进行合并、去重、限制、跳过等操作。
ArrayList<User> dataList1 = new ArrayList<>();
dataList1.add(new User(52,"a"));
dataList1.add(new User(43,"c"));
dataList1.add(new User(82,"b"));
ArrayList<User> dataList2 = new ArrayList<>();
dataList2.add(new User(18,"d"));
dataList2.add(new User(18,"b"));
List<User> collect = Stream.concat(dataList1.stream(), dataList2.stream())
.distinct() //去重,需重写equals方法
.skip(1) //跳过
.collect(Collectors.toList());