- 前面介绍了streams相关的概念,这一节将介绍如何使用streams API。
一、Stream的创建
1、从Collection接口和Arrays类中
- Arrays.stream(T t),我们可以通过Arrays的静态方法,传入一个泛型数组,创建一个流
- Collection.stream,可以用过集合的接口的默认方法,创建一个流;使用这个方法,包括继承Collection的接口,如:Set,List,Map,SortedSet 等等
2、Stream中的静态方法
- Stream.of,我们可以通过Stream的静态方法,传入一个泛型数组,或者多个参数,创建一个流,这个静态方法,也是调用了Arrays的stream静态方法
- Stream.iterate,是Stream接口下的一个静态方法,从名字也可以看出,这个静态方法,是以迭代器的形式,创建一个数据流
二、Stream API使用
1、中间操作intermediate
- 概念:对流中数据元素做出相应的转换或者操作后仍然返回一个流Stream
- 数据准备:
//Person(name,birthday,age)列表
private static List<Person> persons = new ArrayList<>();
static {
persons.add(new Person("1", System.currentTimeMillis(), 11));
persons.add(new Person("2", System.currentTimeMillis() + 6, 15));
persons.add(new Person("3", System.currentTimeMillis() + 9, 9));
persons.add(new Person("4", System.currentTimeMillis() + 22, 21));
persons.add(new Person("5", System.currentTimeMillis() + 14, 5));
}
(1)filter:对Stream中元素进行过滤
//1、过滤出年龄大于10的人
List<Person> afetrFilterPerson = persons.stream()
.filter(person -> person.getAge() > 10)
.collect(Collectors.toList());
System.out.println(afetrFilterPerson);
(2)map:对Stream中元素按照指定规映射成另一个元素(1对1关系)
//2、获取年龄大于10的人的年龄列表
List<Integer> afterMapPerson = persons.stream()
.filter(person -> person.getAge() > 10)
.map(Person::getAge)
.collect(Collectors.toList());
System.out.println(afterMapPerson);
(3)flatMap:将一个流中的每个值都转成一个个流,然后再将这些流扁平化成为一个流 (1对多关系)
//3、map和flatMap区别
List<String> strs = Arrays.asList("好,好,学", "习,天,天", "向,上");
List<String[]> strArray = strs.stream()
.map(str -> str.split(","))
.collect(Collectors.toList());
// flatMap与map的区别在于 flatMap是将一个流中的每个值都转成一个个流,然后再将这些流扁平化成为一个流 。
List<String> strList = strs.stream()
.map(str -> str.split(","))
.flatMap(Arrays::stream)
.collect(Collectors.toList());
System.out.println("strList => " + strList);
(4)concat:对两个Stream进行合并操作
//4、concat合并两个流
List<String> stream1=Arrays.asList("1","2");
List<String> stream2=Arrays.asList("3","2");
List<String> concatStream = Stream.concat(stream1.stream(), stream2.stream()).collect(Collectors.toList());
System.out.println(concatStream);
(5)distinct:对Stream进行去重操作
//5、distinct去重操作,去除相同的两个person
List<Person> afetrDistinctPersons = persons.stream().
distinct().collect(Collectors.toList());
(6)limit:限制Stream中元素的个数
(7)skip:跳过流中前几个元素
(8)peek:对流中每一个元素进行操作,类forEach操作
(9)sorted:对Stream中的元素进行排序,可以自定义比较规则
private static List<User> userList = new ArrayList<User>();
static {
userList.add(new User(1, new Date().getTime()));
userList.add(new User(3, new Date().getTime() + 2));
userList.add(new User(6, new Date().getTime() + 5));
userList.add(new User(1, new Date().getTime() + 1));
}
public static void main(String[] args) {
//1、普通排序(单一按照weight权重排序)
List<User> sortList = userList.stream()
.sorted(Comparator.comparing(User::getWeight))
.collect(Collectors.<User>toList());
sortList.forEach(System.out::println);
//2、反向排序(单一按照weight进行排序)
List<User> reverseSortList = userList.stream()
.sorted(Comparator.comparing(User::getWeight).reversed())
.collect(Collectors.<User>toList());
reverseSortList.forEach(System.out::println);
System.out.println("---------------------");
//3、 按权重从大排到小 相同权重按更新时间从大排到小
List<User> finalSortList = userList.stream().sorted((user1, user2) -> {
if (user1.getWeight().equals(user2.getWeight())) {
return -user1.getCreateTime().compareTo(user2.getCreateTime());
} else {
return -user1.getWeight().compareTo(user2.getWeight());
}
}).collect(Collectors.toList());
finalSortList.forEach(System.out::println);
}
(10)match:检查流中元素是够匹配指定的匹配规则
//流只能操作一次
Stream<Integer> stream = Stream.of(1,2,5,6);
Stream<Integer> stream1 = Stream.of(1,2,5,6);
Stream<Integer> stream2 = Stream.of(1,2,5,6);
//匹配所有
boolean allMatch = stream.allMatch(num->num>1);
System.out.println(allMatch);
//匹配任何一个
boolean anyMatch = stream1.anyMatch(num->num>5);
System.out.println(anyMatch);
//全部不匹配
boolean noneMatch = stream2.noneMatch(num->num>10);
System.out.println(noneMatch);
2、结束操作terminal
- 概念:指最终对Stream做出聚合操作,输出结果
(1)count:统计Stream中元素的个数
(2)max、min:找出流中最大或者最小值
(3)forEach:内部遍历元素
(4)reduce
- reduce操作可以实现从Stream中生成一个值,其值不是随意的,而是根据指定的计算模型生成的。(但是在工作中使用不多,这里就不细讲了)
(5)collect
- collect操作是将一个数据流缩减为一个值得规约操作,这个值可以是集合、映射或者是一个值对象,使用collect可以完成:
1、将数据缩减为一个单一值(单一值可以是collection或者int等的值,或者用户自定义的一个对象)
2、讲一个数据流中的元素进行分组,产生Map<taskType,List<Task>>的结果,其中每一个实体包含一个任务类型以及它相关的任务。也可以产生Map<taskType,Task>等类型
3、分割流中的元素,比如将一个流分割为两组,比如将任务分割为已经做完和要做的两个组。
- collector的实际应用
//已知一个User(name,age)
//1、缩减为一个值
//(1)将数据缩减为一个列表
List<User> userList = users.stream().
collect(Collectors.toList());
//(2)将数据缩减为一个集合
Set<User> userSet = users.stream().
collect(Collectors.toSet());
//(3)将数据缩减为一个映射
//重复的键会抛异常
//Map<String, User> userMap = users.stream().
//collect(Collectors.toMap(User::getName,user->user));
//允许指定一个合并方法,这个合并方法允许用户指定想如何处理多个值关联到同一个键的冲突
Map<String, User> userMap1 = users.stream().
collect(Collectors.toMap(User::getName,user->user,(t1,t2)->t2));
//指定其他的映射结果
Map<String, User> userMap2 = users.stream().
collect(Collectors.toMap(User::getName,user->user,
(t1,t2)->t1, LinkedHashMap::new));
System.out.println(userMap1);
System.out.println(userMap2 instanceof LinkedHashMap);
//-------------------------------------------------------------------------------------------------
//2、分类收集器
//(1)根据名称对user分类
Map<String, List<User>> groupByName = users.stream().
collect(Collectors.groupingBy(User::getName));
//(2)先根据名称分类然后根据年龄
Map<String, Map<Integer, List<User>>> doubleGroupBy = users.stream().
collect(Collectors.groupingBy(User::getName,Collectors.groupingBy(User::getAge)));
//(3)根据name分类后统计出每一个类别的数量
Map<String, Long> groupMapToCounting = users.stream().
collect(Collectors.groupingBy(User::getName,Collectors.counting()));
//(4)先根据name分类然后对分类后的user进行map操作
Map<String, List<Integer>> collect = users.stream().
collect(Collectors.groupingBy(User::getName,
Collectors.mapping(User::getAge, Collectors.toList())));
//---------------------------------------------------------------------------
//3、生成统计信息
double average = users.stream().collect(Collectors.summarizingInt(User::getAge)).getAverage();
//--------------------------------------------------------------------------
//4、连接操作
String nameJoining = users.stream().map(User::getName).collect(Collectors.joining(","));
}