Stream流
一.stream流的获取
1.Collection集合可以直接通过stream方法获取stream流
// 集合获取流
// Collection接口中的方法: default Stream<E> stream() 获取流
List<String> list = new ArrayList<>();
// ...
Stream<String> stream1 = list.stream();
Set<String> set = new HashSet<>();
// ...
Stream<String> stream2 = set.stream();
Vector<String> vector = new Vector<>();
// ...
Stream<String> stream3 = vector.stream();
// Map获取流
Map<String, String> map = new HashMap<>();
// ...
Stream<String> keyStream = map.keySet().stream();
Stream<String> valueStream = map.values().stream();
Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();
2.Stream中的静态方法of获取流
// Stream中的静态方法: static Stream of(T... values)
Stream<String> stream6 = Stream.of("aa", "bb", "cc");
String[] arr = {"aa", "bb", "cc"};
Stream<String> stream7 = Stream.of(arr);
Integer[] arr2 = {11, 22, 33};
Stream<Integer> stream8 = Stream.of(arr2);
// 注意:基本数据类型的数组不行
int[] arr3 = {11, 22, 33};
Stream<int[]> stream9 = Stream.of(arr3);
二.stream流的常见方法
终结方法:返回值类型不再是 Stream 类型的方法,不再支持链式调用。
非终结方法:返回值类型仍然是 Stream 类型的方法,支持链式调用。
1.foreach方法
void forEach(Consumer<? super T> action);
该方法接收一个 Consumer 接口函数,会将每一个流元素交给该函数进行处理。例如:
List<String> strings = new ArrayList<String>();
@Test
public void streamDemo(){
Collections.addAll(strings,"王平","王武","王林","陈平安");
strings.stream().forEach((String s)->{
System.out.println(s);
});
//简写
//strings.stream().forEach(System.out::println);
}
2.count方法
long count();
该方法返回其中元素个数,例如:
@Test
public void streamCount(){
Collections.addAll(strings,"王平","王武","王林","陈平安");
System.out.println(strings.stream().count());
}
3.filter方法
Stream<T> filter(Predicate<? super T> predicate);
该接口接收一个 Predicate 函数式接口参数(可以是一个Lambda或方法引用)作为筛选条件。
Stream流中的 filter 方法基本使用的代码如:
@Test
public void streamFilter(){
Collections.addAll(strings,"王平","王武","王林","陈平安","平");
strings.stream().filter(s->s.length()==3).forEach(System.out::println);
strings.stream().filter(s->s.length()>=2 || s.length()==3).forEach(System.out::println);
}
4.skip方法
Stream<T> skip(long n);
如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流。例如:
@Test
public void streamSkip(){
Collections.addAll(strings,"王平","王武","王林","陈平安");
strings.stream().skip(1).forEach(System.out::println);
}
5.limit方法
Stream<T> limit(long maxSize);
参数是一个long型,如果集合当前长度大于参数则进行截取。否则不进行操作。例如:
@Test
public void streamLimit(){
Integer[] ints = {1,2,3,4,5,6,7,8,9};
Stream.of(ints).limit(7).skip(3).forEach(System.out::println);
}
6.map方法
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
该接口需要一个 Function 函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。
Stream流中的 map 方法基本使用的代码如:
@Test
public void streamMap(){
Collections.addAll(strings,"1","2","3");
/*strings.stream().map((String s) ->{
return Integer.parseInt(s);
}).forEach(System.out::println);*/
strings.stream().map(Integer::parseInt).forEach(System.out::println);
}
7.sorted方法
Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);
如果需要将数据排序,可以使用 sorted 方法,例如:
@Test
public void streamSorted(){
// Stream.of(33,11,22,44).sorted().forEach(System.out::println);
Stream.of(33,11,22,44).sorted(
(i1,i2)->i2- i1
).forEach(System.out::println);
Collections.addAll(strings,"王平","王武","王林","陈平安");
strings.stream().sorted((s1,s2)-> s2.compareTo(s1) ).forEach(System.out::println);
/*在sorted中自定义的比较器中,只要是用前一个参数的值比较后一个数的值就是升序排序,
只要是用后一个参数的值比较前一个数的值就是降序排序。如果是字符串比较就是用compareTo,
如果是数值比较就用相应的compare比较*/
}
8.distince方法
Stream<T> distinct();
如果需要去除重复数据,可以使用 distinct 方法。例如:
@Test
public void streamDistinct(){
Stream.of(33,11,22,44,11,new Integer(55),new Integer(55)).distinct().forEach(System.out::println);
//自定义类型去重
//自定义类型是根据对象的hashCode和equals来去除重复元素。
Stream.of(
new Demo("小王",5),
new Demo("小王",8),
new Demo("小王",5)
).distinct().forEach(System.out::println);
}
9.match方法
boolean allMatch(Predicate<? super T> predicate);
boolean anyMatch(Predicate<? super T> predicate);
boolean noneMatch(Predicate<? super T> predicate);
Stream流中的 Match 相关方法基本使用的代码如:
@Test
public void streamMatch(){
Stream<Integer> stream = Stream.of(33, 11, 22, 44, 11);
//AllMatch匹配所有元素,所有元素都需要满足条件
// System.out.println(stream.allMatch(i -> i > 0));
//AnyMatch匹配某个元素,只要某个元素满足条件即可
// System.out.println(stream.anyMatch(i -> i > 0));
//NoneMatch匹配所有元素,所有元素都不能满足条件
System.out.println(stream.noneMatch(i -> i<0));
}
10.find方法
Optional<T> findFirst();
Optional<T> findAny();
代码:
@Test
public void streamFind(){
Stream<Integer> stream = Stream.of(33, 11, 22, 44);
// System.out.println(stream.findFirst().get()); //findFirst作用是从Stream抽取第一个元素
System.out.println(stream.findAny().get());
//findAny作用就是从Stream中取任意一个元素,正常情况下一般会取第一个元素,在并行流的情况下会随机取一个元素
}
11.max方法和min方法
Optional<T> max(Comparator<? super T> comparator);
Optional<T> min(Comparator<? super T> comparator);
代码:
@Test
public void streamMaxAndMin(){
Optional<Integer> max = Stream.of(5, 3, 6, 1).max(Integer::compare);
System.out.println("max = " + max.get());
Optional<Integer> min = Stream.of(5, 3, 6, -1).min((o1, o2) -> o1 - o2);
System.out.println("min = " + min.get());
}
12.reduce方法
T reduce(T identity, BinaryOperator<T> accumulator);
参数:T identity 默认值
BinaryOperator<T> accumulator 对数据进行处理的方式
代码:
@Test
public void streamReduce(){
Stream<Integer> stream = Stream.of(33, 11, 22, 44);
// 利用reduce求和
// 第一次将默认做赋值给x, 取出第一个元素赋值给y,进行操作
// 第二次,将第一次的结果赋值给x, 取出二个元素赋值给y,进行操作
// 第三次,将第二次的结果赋值给x, 取出三个元素赋值给y,进行操作
// 第四次,将第三次的结果赋值给x, 取出四个元素赋值给y,进行操作
// stream.reduce(0, (a, b) -> {
// System.out.println("a = " + a + ", b = " + b);
// return a + b;
// });
// System.out.println(stream.reduce(0, Integer::sum));
//利用reduce求最大值或最小值
System.out.println(stream.reduce(0, (a, b) -> {
// return a > b ? a : b;
return a<b ?a : b;
}));
}
三.stream的注意事项
1. Stream只能操作一次
2. Stream方法返回的是新的流
3. Stream不调用终结方法,中间的操作不会执行
文章参考:(https://www.bilibili.com/video/BV1zJ411R7uQ/)