Stream的概述
Stream是java 8新增的特性,用来补充集合类。
Stream就是流,流中的数据元素的数量可以是有限个数,也可能是无限个数。
Stream的特性
- 不存储数据:流失基于数据源的对象,它本身不存储数据元素,而是通过管道蒋淑媛的元素传递操作。
- 函数式编程:流在每一级的操作中,都会新创建一个副本,例如执行filter不会将数据源中的数据进行删除。
- 具有顺序不可逆性:每一个级别的操作都是按照编写的顺序进行的,下一个操作会基于上一个操作。
流的创建方法
- 使用Collection.stream()直接获取流对象
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream(); //获取一个顺序流
Stream<String> parallelStream = list.parallelStream(); //获取一个并行流
- 数组直接转成流对象
Integer[] nums = new Integer[10];
Stream<Integer> stream = Arrays.stream(nums);
- 使用Stream中的静态方法:of(),iterate(),generate()
Stream<Integer> stream = Stream.of(1,2,3,4,5,6);
Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 2).limit(6);
stream2.forEach(System.out::println); // 0 2 4 6 8 10
Stream<Double> stream3 = Stream.generate(Math::random).limit(2);
stream3.forEach(System.out::println);
- 使用 BufferedReader.lines() 方法,将每行内容转成流
BufferedReader reader = new BufferedReader(new FileReader("F:\\test_stream.txt"));
Stream<String> lineStream = reader.lines();
lineStream.forEach(System.out::println);
- 使用 Pattern.splitAsStream() 方法,将字符串分隔成流
Pattern pattern = Pattern.compile(",");
Stream<String> stringStream = pattern.splitAsStream("a,b,c,d");
stringStream.forEach(System.out::println);
流的操作(流的操作包括中间操作和终端操作,中间操作通常是一些过滤,求值操作,终端操作为统计,或者转换为某种容器的操作)
流的中间操作
- filter(表达式):过滤流中的某些元素,获取流中符合表达式的元素
Stream<Integer> integerStream=Stream.of(1,2,3,4,5,6);
List<Integer> integerList=integerStream
.filter(integer -> integer.intValue()<5)
.collect(Collectors.toList());
System.out.println(integerList);
结果为:
-limit(n):n为数值,获取流中的前n个元素
Stream<Integer> integerStream=Stream.of(1,2,3,4,5,6);
List<Integer> integerList=integerStream
.filter(integer -> integer.intValue()<5)
.limit(3)
.collect(Collectors.toList());
System.out.println(integerList);
-skip(n):跳过前n元素,配合limit(n)可实现分页
Stream<Integer> integerStream=Stream.of(1,2,3,4,5,6);
List<Integer> integerList=integerStream
.filter(integer -> integer.intValue()<5)
.limit(3)
.skip(2)
.collect(Collectors.toList());
System.out.println(integerList);
原本应该是[1,2,3],调用skip(2)后,跳过前面两个元素
- distinct:通过流中元素的 hashCode() 和 equals() 去除重复元素
Stream<Integer> integerStream=Stream.of(1,2,2,4,5,6,6,7,8);
List<Integer> integerList=integerStream
.skip(2)
.distinct()
.collect(Collectors.toList());
System.out.println(integerList);
- 映射:
- map:接收一个函数作为参数,该函数会被应用到每一个元素上,并将其根据函数转换成为一个新的元素。
Stream<Integer> integerStream=Stream.of(1,2,2,4,5,6,6,7,8);
List<Integer> integerList=integerStream
.map(integer -> integer+2)
.collect(Collectors.toList());
System.out.println(integerList);
- flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后将所有的流连接成为一个流。
public static List<Integer> getLessThan(Integer integer) {
return Stream.iterate(0, x -> x + 1).limit(integer).collect(Collectors.toList());
}
public static void main(String[] args) {
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4);
List<Integer> integerList = integerStream.flatMap(s -> {
return getLessThan(s).stream();
})
.collect(Collectors.toList());
System.out.println(integerList);
}
- 排序
- sorted():自然排序,流中的元素需实现Comparable接口
- sorted(Comparator comparator ):定制排序,自定义Comparator排序器
自然排序:
先实现comparable接口
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Comparable<User> {
private String name;
private Integer age;
private String phone;
@Override
public int compareTo(User user) {
return user.age-this.getAge();
}
}
List<User> userList=new ArrayList<>();
User user=new User("张三",22,"17806533481");
User user2=new User("李四",27,"18906533481");
User user3=new User("王老五",28,"15806533481");
userList.add(user);
userList.add(user2);
userList.add(user3);
List<User> list=userList.stream().sorted().collect(Collectors.toList());
System.out.println(list);
自定义排序:不需要实现comparable接口,直接使用比较器
List<User> userList=new ArrayList<>();
User user=new User("张三",29,"17806533481");
User user2=new User("李四",27,"18906533481");
User user3=new User("王老五",28,"15806533481");
User user4=new User("赵六",27,"15806533481");
userList.add(user);
userList.add(user2);
userList.add(user3);
userList.add(user4);
List<User> list=userList.stream().sorted((o1,o2)->{
if (o1.getAge()> o2.getAge()){
return 1;
}else if (o1.getAge()<o2.getAge()){
return -1;
}else {
return 0;
}
}).collect(Collectors.toList());
System.out.println(list);
结果按照age升序
- 消费
如同于map,能获得流中的每一个元素,但是map接受的是Function表达式,具有返回值,而peek接受的是Consumer表达式,没有返回值,只进行消费,可以是输出,或者是外部处理。
List<User> userList=new ArrayList<>();
User user=new User("张三",29,"17806533481");
User user2=new User("李四",27,"18906533481");
User user3=new User("王老五",28,"15806533481");
User user4=new User("赵六",27,"15806533481");
userList.add(user);
userList.add(user2);
userList.add(user3);
userList.add(user4);
userList.stream().peek(System.out::println)
.collect(Collectors.toList());
流的终端操作
allmatch,noneMatch,anyMatch用于对集合中对象的某一个属性值进行判断,
allMatch全部符合该条件返回true,
noneMatch全部不符合该断言返回true
anyMatch 任意一个元素符合该断言返回true
- allMatch
List<User> userList=new ArrayList<>();
User user=new User("张三",29,"17806533481");
User user2=new User("李四",27,"18906533481");
User user3=new User("王老五",28,"15806533481");
User user4=new User("赵六",27,"15806533481");
userList.add(user);
userList.add(user2);
userList.add(user3);
userList.add(user4);
boolean allMatch= userList.stream().allMatch(user1 -> user1.getAge()<30);
System.out.println(allMatch);
结果为true;
- noneMatch
List<User> userList=new ArrayList<>();
User user=new User("张三",29,"17806533481");
User user2=new User("李四",27,"18906533481");
User user3=new User("王老五",28,"15806533481");
User user4=new User("赵六",27,"15806533481");
userList.add(user);
userList.add(user2);
userList.add(user3);
userList.add(user4);
boolean noneMatch= userList.stream().noneMatch((user1 -> user1.getAge()>30));
System.out.println(noneMatch);
判断user.age()是不是没有任何一个大于30,结果是的
- anyMatch
List<User> userList=new ArrayList<>();
User user=new User("张三",29,"17806533481");
User user2=new User("李四",27,"18906533481");
User user3=new User("王老五",31,"15806533481");
User user4=new User("赵六",27,"15806533481");
userList.add(user);
userList.add(user2);
userList.add(user3);
userList.add(user4);
boolean anyMatch= userList.stream().anyMatch((user1 -> user1.getAge()>30));
System.out.println(anyMatch)
判断是否至少有一个,符合条件。
findFirst:返回流中第一个元素
findAny:返回流中的任意元素
List<User> userList = new ArrayList<>();
User user = new User("张三", 29, "17806533481");
User user2 = new User("李四", 27, "18906533481");
User user3 = new User("王老五", 31, "15806533481");
User user4 = new User("赵六", 27, "15806533481");
userList.add(user);
userList.add(user2);
userList.add(user3);
userList.add(user4);
User userFirst =userList.stream().findFirst().get();
System.out.println(userFirst);
count:返回流中元素的总个数
List<User> userList = new ArrayList<>();
User user = new User("张三", 29, "17806533481");
User user2 = new User("李四", 27, "18906533481");
User user3 = new User("王老五", 31, "15806533481");
User user4 = new User("赵六", 27, "15806533481");
userList.add(user);
userList.add(user2);
userList.add(user3);
userList.add(user4);
Long aLong =userList.stream().count();
System.out.println(aLong);
max:返回流中元素最大值
List<User> userList = new ArrayList<>();
User user = new User("张三", 29, "17806533481");
User user2 = new User("李四", 27, "18906533481");
User user3 = new User("王老五", 31, "15806533481");
User user4 = new User("赵六", 27, "15806533481");
userList.add(user);
userList.add(user2);
userList.add(user3);
userList.add(user4);
User userMax = userList.stream().max((u1, u2) -> {
if (u1.getAge() > u2.getAge()) {
return 1;
} else if (u1.getAge() < u2.getAge()) {
return -1;
} else {
return 0;
}
}).get();
System.out.println(userMax);
min:返回流中元素最小值
List<User> userList = new ArrayList<>();
User user = new User("张三", 29, "17806533481");
User user2 = new User("李四", 27, "18906533481");
User user3 = new User("王老五", 31, "15806533481");
User user4 = new User("赵六", 20, "15806533481");
userList.add(user);
userList.add(user2);
userList.add(user3);
userList.add(user4);
User userMin = userList.stream().min((u1, u2) -> {
if (u1.getAge() > u2.getAge()) {
return 1;
} else if (u1.getAge() < u2.getAge()) {
return -1;
} else {
return 0;
}
}).get();
System.out.println(userMin);