[java]19、Stream流
1、Stream流
在对流进行处理时,不同的流操作以级联的方式形成处理流水线。一个流水线由一个源(source),0 到多个中间操作(intermediate operation)和一个终结操作(terminal operation)完成。
stream流public class Demo02Stream {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
List<String> listA = new ArrayList<>();
for (String s : list) {
if (s.startsWith("张")) {
listA.add(s);
}
}
//
List<String> listB = new ArrayList<>();
for (String s : listA) {
if (s.length() == 3) {
listB.add(s);
}
}
for (String s : listB) {
System.out.println(s);
}
// 使用stream流操作
list.stream()
.filter(name->name.startsWith(","))
.filter(name->name.length() == 3)
.forEach(name->System.out.println(name));
}
}
2、获取流
java.util.stream.Stream<T>是Java 8新加入的最常用的流接口。(这并不是一个函数式接口。)
获取一个流非常简单,有以下几种常用的方式:
- 所有的Collection集合都可以通过stream默认方法获取流;
default Stream<E> stream() - Stream接口的静态方法of可以获取数组对应的流。
static <T> Stream<T> of(T... values)
参数是一个可变参数,那么我们就可以传递一个数组
public class Demo03GetStream {
public static void main(String[] args) {
//把集合转换为Stream流
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
Set<String> set = new HashSet<>();
Stream<String> stream2 = set.stream();
Map<String, String> map = new HashMap<>();
// 存储到set集合中
Set<String> keyset = map.keySet();
Stream<String>stream3 = keyset.stream();
// 存储到一个Collection集合中
Collection<String> values = map.values();
Stream<String> stream4 = values.stream();
// 获取键值对的映射关系entrySet
Set<Map.Entry<String, String>> entries = map.entrySet();
Stream<Map.Entry<String, String>> stream5 = entries.stream();
// 把数组转换为stream流
Stream<Integer> stream6 = Stream.of(1, 2, 3, 4);
// 可变参数传递数组
Integer[] arr = {1, 2, 3, 4};
Stream<Integer> stream7 = Stream.of(arr);
}
}
3、常用方法
流的模式很丰富,这里可以分为两种
- 延迟方法: 返回值类型仍然是Stream接口自身类型的方法,因此支持链式调用。(除了终结方法外,其余方法均为延迟方法)
- 终结方法:返回值不在是Stream接口自身类型的方法,因此不再支持类似StringBuilder那样的链式调用。
1、forEach
Stream流中的常用方法_forEach
void forEach(Consumer<? super T> action);
该方法接收一个Consumer接口函数,会将每一个流元素交给该函数进行处理。
Consumer接口是一个消费型的函数式接口,可以传递Lambda表达式,消费数据
简单记:
forEach方法,用来遍历流中的数据
是一个终结方法,遍历之后就不能继续调用Stream流中的其他方法
// 获取一个stream流
Stream<String> stream = Stream.of("张三", "李四", "王五", "赵六", "田七");
stream.forEach((name)->System.out.println(name));
2、filter
Stream流中的常用方法_filter:用于对Stream流中的数据进行过滤
Stream<T> filter(Predicate<? super T> predicate);
filter方法的参数Predicate是一个函数式接口,所以可以传递Lambda表达式,对数据进行过滤
Predicate中的抽象方法:
boolean test(T t);
Stream<String> stream = Stream.of("张无忌", "周芷若", "赵敏", "张强", "张三丰");
Stream<String> stream1 = stream.filter((name)->name.startsWith("张"));
stream1.forEach((name)->System.out.println(name));
// Stream流属于管道流,只能被消费一次
// 第一个Stream流调用完毕方法,数据就会流转到下一个Stream上
// 而第一个Stream流已经使用完毕,就会关闭了
// 所以第一个Stream流就不能调用方法了
3、map
Stream流中的常用方法_map:用于类型转换
如果需要将流中的元素映射到另一个流中,可以使用map方法.
public class Demo05Stream_map {
public static void main(String[] args) {
Stream<String> stream = Stream.of("1", "2", "3", "4");
// 使用map方法将字符串类型转换为Int类型
stream.map(s -> Integer.parseInt(s));
stream.forEach(i -> System.out.println(i));
}
}
4、count
Stream流中的常用方法_count:用于同级Stream流中元素的个数
count方法是一个终结方法,返回值是一个long类型的整数
所以不能在继续调用Stream流中的其他方法了
public class Demo06Stream_count {
public static void main(String[] args) {
// 获取一个特stream流
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
Stream<Integer> stream = list.stream();
System.out.println(stream.count());
}
}
5、limit
Stream流中的常用方法_limit:用于截取流中的元素
limit方法可以对流进行截取,只取用前n个
limit方法是一个延迟方法,只是对流中的元素进行截取,返回的是一个新的流,所以可以继续调用Stream流中的其他方法
public class Demo07Stream_limit {
public static void main(String[] args) {
String[] arr = {"喜羊羊", "美羊羊", "懒羊羊", "灰太狼"};
Stream<String> stream = Stream.of(arr);
Stream<String> stream2 = stream.limit(3);
stream2.forEach(name->System.out.println(name));
}
}
6、skip
Stream流中的常用方法_skip:用于跳过元素
如果希望跳过前几个元素,可以使用skip方法获取一个截取之后的新流:
Stream<T> skip(long n);
如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流。
skip
public class Demo08Stream_skip {
public static void main(String[] args) {
String[] arr = {"喜羊羊", "美羊羊", "懒羊羊", "灰太狼"};
Stream<String> stream = Stream.of(arr);
Stream<String> stream2 = stream.skip(2);
stream2.forEach(name->System.out.println(name));
}
}
7、concat
Stream流中的常用方法_concat:用于把流组合到一起
如果有两个流,希望合并成为一个流,那么可以使用Stream接口的静态方法concat
public class Demo09Stream_concat {
public static void main(String[] args) {
Stream<String> stream = Stream.of("张无忌", "周芷若", "赵敏", "张强", "张三丰");
String[] arr = {"喜羊羊", "美羊羊", "懒羊羊", "灰太狼"};
Stream<String> stream1 = Stream.of(arr);
Stream<String> stream2 = Stream.concat(stream, stream1);
// 遍历stream
stream2.forEach(name->System.out.println(name));
}
}
4、练习
用集合实现如下操作
public class Demo10StreamTest {
public static void main(String[] args) {
ArrayList<String>one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("石破天");
one.add("石中玉");
// 成员名字长度为3;存储到一个新的集合中
ArrayList<String> one1 = new ArrayList<>();
for (String s : one) {
if (s.length() == 3) {
one1.add(s);
}
}
// 只要前三个人
ArrayList<String> one2 = new ArrayList<>();
for (int i = 0; i < 3; i ++) {
one2.add(one1.get(i));
}
ArrayList<String>two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("赵丽颖");
two.add("张三丰");
two.add("张天爱");
two.add("张二狗");
// 只要姓张的
ArrayList<String> two1 = new ArrayList<>();
for (String s : two) {
if (s.startsWith("张")) {
two1.add(s);
}
}
// 第二个队列不要钱两个人
ArrayList<String> two2 = new ArrayList<>();
for (int i = 2; i < two1.size(); i++) {
two2.add(two1.get(i)); // i 不包含01
}
// 合并队伍
ArrayList<String> all = new ArrayList<>();
all.addAll(one2);
all.addAll(two2);
// 存储到Person中
ArrayList<Person> list = new ArrayList<>();
for (String name : all) {
list.add(new Person(name));
}
System.out.println(list);
}
}
在用stream流实现上述操作
public class Demo10Stream_stream {
public static void main(String[] args) {
ArrayList<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("石破天");
one.add("石中玉");
Stream<String> stream1 = one.stream();
Stream<String>streamOne = stream1.filter(name->name.length() == 3).limit(3);
ArrayList<String>two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("赵丽颖");
two.add("张三丰");
two.add("张天爱");
two.add("张二狗");
Stream<String> stream2 = two.stream();
Stream<String> streamTwo = stream2.filter(s->s.startsWith("张")).skip(2);
Stream.concat(streamOne, streamTwo).map(name-> new Person(name)).forEach(p->System.out.println(p));
}
}