Stream流
1.概述
在Java 8中,得益于Lambda所带来的函数式编程,引入了一个全新的Stream概念,用于解决已有集合类库既有的弊端。
2.获取流方式
java.util.stream.Stream 是Java 8新加入的最常用的流接口。(这并不是一个函数式接口。)
获取一个流非常简单,有以下几种常用的方式:
所有的 Collection 集合都可以通过 stream 默认方法获取流;
Stream 接口的静态方法 of 可以获取数组对应的流。
3.常用方法
forEach : 逐一处理
虽然方法名字叫 forEach ,但是与for循环中的“for-each”昵称不同,该方法并不保证元素的逐一消费动作在流中是被有序执行的。
void forEach(Consumer<? super T> action);
package liu;
import java.util.function.Consumer;
import java.util.stream.Stream;
public class Demo01 {
public static void main(String[] args) {
Stream<String> str = Stream.of("大娃","二娃","三娃","四娃","五娃","六娃","七娃","爷爷","蛇精","蝎子精");
/* str.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
/* str.forEach((String s) -> {
System.out.println(s);
});*/
str.forEach((s) -> System.out.println(s));
}
}
filter:过滤
package liu;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class Demo02 {
public static void main(String[] args) {
Stream<String> str = Stream.of("大娃", "二娃", "三娃", "四娃", "五娃", "六娃", "七娃", "爷爷", "蛇精", "蝎子精");
//匿名内部类写法
/* str.filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.contains("娃");
}
}).forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
//表达式写法
str.filter( s ->
s.contains("娃")
).forEach(s -> System.out.println(s));
}
}
count:统计个数
正如旧集合 Collection 当中的 size 方法一样,流提供 count 方法来数一数其中的元素个数:
long count();
该方法返回一个long值代表元素个数(不再像旧集合那样是int值)。基本使用:
package liu;
import java.util.stream.Stream;
public class Demo03 {
public static void main(String[] args) {
Stream<String> str = Stream.of("大娃", "二娃", "三娃", "四娃", "五娃", "六娃", "七娃", "爷爷", "蛇精", "蝎子精");
long num = str.count();
System.out.println(num);
}
}
limit:取用前几个
limit 方法可以对流进行截取,只取用前n个。方法签名:
Stream limit(long maxSize):获取Stream流对象中的前n个元素,返回一个新的Stream流对象
参数是一个long型,如果集合当前长度大于参数则进行截取;否则不进行操作。
skip:跳过前几个
如果希望跳过前几个元素,可以使用 skip 方法获取一个截取之后的新流:
Stream skip(long n): 跳过Stream流对象中的前n个元素,返回一个新的Stream流对象
如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流。
package liu;
import java.util.stream.Stream;
public class Demo04 {
public static void main(String[] args) {
Stream<String> str = Stream.of("大娃", "二娃", "三娃", "四娃", "五娃", "六娃", "七娃", "爷爷", "蛇精", "蝎子精");
Stream<String> s1 = str.limit(7);
Stream<String> s2 = s1.skip(3);
s2.forEach((s) -> System.out.println(s));
}
}
concat:组合
如果有两个流,希望合并成为一个流,那么可以使用 Stream 接口的静态方法 concat :
static Stream concat(Stream<? extends T> a, Stream<? extends T> b): 把参数列表中的两个
Stream流对象a和b,合并成一个新的Stream流对象
备注:这是一个静态方法,与 java.lang.String 当中的 concat 方法是不同的。
package liu;
import java.util.stream.Stream;
public class Demo05 {
public static void main(String[] args) {
Stream<String> s1 = Stream.of("大娃", "二娃", "三娃", "四娃", "五娃", "六娃", "七娃");
Stream<String> s2 = Stream.of("爷爷", "蛇精", "蝎子精");
Stream<String> s3 = Stream.concat(s1, s2);
s3.forEach((name) -> System.out.println(name));
}
}
4.综合案例
传统方式:
package liu;
import java.util.ArrayList;
import java.util.List;
/*1. 第一个队伍只要名字为3个字的成员姓名;
2. 第一个队伍筛选之后只要前3个人;
3. 第二个队伍只要姓张的成员姓名;
4. 第二个队伍筛选之后不要前2个人;
5. 将两个队伍合并为一个队伍;
6. 打印整个队伍的姓名信息。*/
public class Demo06 {
public static void main(String[] args) {
List<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("老子");
one.add("庄子");
one.add("孙子");
one.add("洪七公");
//第一个队伍只要名字为3个字的成员姓名;
ArrayList<String> one1 = new ArrayList<>();
for (String a:one) {
if (a.length() == 3){
one1.add(a);
}
}
//第一个队伍筛选之后只要前3个人
ArrayList<String> one2 = new ArrayList<>();
for (int i = 0; i < 3; i++) {
one2.add(one1.get(i));
}
List<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("张三丰");
two.add("赵丽颖");
two.add("张二狗");
two.add("张天爱");
two.add("张三");
//第二个队伍只要姓张的成员姓名
ArrayList<String> two1 = new ArrayList<>();
for (String a:two) {
if (a.startsWith("张")){
two1.add(a);
}
}
//第二个队伍筛选之后不要前2个人
ArrayList<String> two2 = new ArrayList<>();
for (int i = 2; i < two1.size() ; i++) {
two2.add(two1.get(i));
}
//将两个队伍合并为一个队伍
ArrayList<String> list = new ArrayList<>();
list.addAll(one2);
list.addAll(two2);
//打印整个队伍的姓名信息。
for (String b:list) {
System.out.println(b);
}
}
}
Stream流的方式:
package liu;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
/*1. 第一个队伍只要名字为3个字的成员姓名;
2. 第一个队伍筛选之后只要前3个人;
3. 第二个队伍只要姓张的成员姓名;
4. 第二个队伍筛选之后不要前2个人;
5. 将两个队伍合并为一个队伍;
6. 打印整个队伍的姓名信息。*/
public class Demo07 {
public static void main(String[] args) {
List<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("老子");
one.add("庄子");
one.add("孙子");
one.add("洪七公");
List<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("张三丰");
two.add("赵丽颖");
two.add("张二狗");
two.add("张天爱");
two.add("张三");
ArrayList<String> list = new ArrayList<>();
Stream.concat(
one.stream().filter(name -> name.length() == 3).limit(3),
two.stream().filter(name -> name.startsWith("张")).skip(2)
).forEach(name -> System.out.println(name));
}
}