社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
JavaEE学习日志持续更新----> 必看!JavaEE学习路线(文章总汇)
Stream:就是一个流式思想,可以把集合或数组,转化为一个Stream流,使用Stream流中的方法,来操作集合或数组
现在,我们有一个集合,它有以下元素
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
需求:过滤掉集合中以张开头的元素,然后过滤掉字符串长度为3的元素,最后再遍历输出每个元素
使用传统的方式(循环遍历),对集合中的元素进行过滤,并遍历集合
public class Demo01 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
//对list集合中的元素进行过滤,只要以张开头的元素,存储到一个新的集合
List<String> listZhang = new ArrayList<>();
for (String name : list) {
if(name.startsWith("张")){
listZhang.add(name);
}
}
//对listZhang集合中的元素进行过滤,只要名字长度为3的元素,存储到一个新的集合
List<String> listThree = new ArrayList<>();
for (String name : listZhang) {
if(name.length()==3){
listThree.add(name);
}
}
//遍历listThree
for (String name : listThree) {
System.out.println(name);
}
}
}
这段代码中含有三个循环,每一个作用不同:
每当我们需要对集合中的元素进行操作的时候,总是需要进行循环、循环、再循环。这是理所当然的么?不是。循环是做事情的方式,而不是目的。另一方面,使用线性循环就意味着只能遍历一次。如果希望再次遍历,只能再使用另一个循环从头开始。
所以就有了Lambda的衍生物Stream
示例:Stream可以使代码更加优雅
public class Demo02 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
//对list集合中的元素进行过滤,只要以张开头的元素,存储到一个新的集合
//对listZhang集合中的元素进行过滤,只要名字长度为3的元素,存储到一个新的集合
//遍历listThree
//把list转化为流
/*list.stream()
.filter(name->name.startsWith("张"))
.filter(name->name.length()==3)
.forEach(name->System.out.println(name));*/
//方法引用
list.stream()
.filter(name->name.startsWith("张"))//过滤以张开头的元素
.filter(name->name.length()==3)//过滤长度为3的元素
.forEach(System.out::println);//遍历
}
}
Stream流:需要先创建一条流式模型,根据模型操作数据
注意:
java.util.stream.Stream<泛型> 是Java 8新加入的最常用的流接口
获取Stream流的方式
default Stream<E> stream()
:返回以此集合为源的顺序 Stream 。static <T> Stream<T> of(T... values)
:传递可变参数,把可变参数转换为Stream流。示例一:Collection集合获取Stream流
//创建list集合
List<String> list = new ArrayList<>();
//使用List集合中的方法stream,把集合转化为流
Stream<String> stream1 = list.stream();
//创建set集合
Set<String> set = new HashSet<>();
//使用set集合中的方法stream,把集合转化为流
Stream<String> stream2 = set.stream();
//第一种:转化为set或Colleciton集合来获取流
Map<String,String> map = new HashMap<>();
Set<String> keySet = map.keySet();//获取所有的键
Stream<String> stream3 = keySet.stream();
Collection<String> values = map.values();//获取所有的值
Stream<String> stream4 = values.stream();
//第二种:通过entry来获取流
Set<Map.Entry<String, String>> entries = map.entrySet();
Stream<Map.Entry<String, String>> stream5 = entries.stream();
示例二:数组获取Stream流
//Stream接口的静态方法of创建stream流
Stream<String> stream1 = Stream.of("a", "b", "c", "d");
Stream<Integer> stream2 = Stream.of(1,2,3,4);
//可变参数底层就是一个数组,所以也可以传递数组,创建Stream流
String[] arr1 = {"a", "b", "c", "d"};
Stream<String> stream3 = Stream.of(arr1);
Integer[] arr2 = {1,2,3,4};
Stream<Integer> stream4 = Stream.of(arr2);
注意:以下写法错误,数组的数据类型必须使用包装类,不能使用基本类型
int[] arr3 = {1,2,3,4,5};
Stream<int[]> stream5 = Stream.of(arr3);
Stream流的方法分为两种方法:
void forEach(Consumer<? super T> action)
对此流的每个元素执行操作。
是一个终结方法,返回值不是Stream,不能再使用Stream中的方法了。
参数:函数式接口Consumer,所以可以使用lambda表达式,重写accept方法
作用:对Stream流进行遍历
示例:
public class Demo02 {
public static void main(String[] args) {
//创建一个Stream流
Stream<String> stream = Stream.of("美羊羊", "喜羊羊", "慢羊羊", "懒羊羊", "沸羊羊", "灰太狼", "红太狼", "小灰灰");
//方法引用
stream.forEach(System.out::println);
}
}
注意:若使用了两次Stream流,则会报IllegalStateException: stream has already been operated upon or closed
异常。第二次使用Stream中的方法forEach,抛出了非法的状态异常,流是一个流式模型,流使用完毕之后,数据就流转到下一步,这时上一步的流就已经关闭,所以就不能再使用了,Stream流只能使用一次。
public class Demo02 {
public static void main(String[] args) {
//创建一个Stream流
Stream<String> stream = Stream.of("美羊羊", "喜羊羊", "慢羊羊", "懒羊羊", "沸羊羊", "灰太狼", "红太狼", "小灰灰");
//第一次使用Stream流
stream.forEach( s-> System.out.println(s));
//第二次使用Stream流,出现异常!
stream.forEach(System.out::println);
}
}
Stream<T> filter(Predicate<? super T> predicate)
返回由与此给定谓词匹配的此流的元素组成的流。
参数:函数式接口Predicate,所以可以使用lambda表达式,重写test方法
作用:对Stream流中的元素进行过滤,形成一个新的Stream流
示例:对Stream流中的元素进行过滤,只要包含"羊羊",并对新Stream流进行遍历
public class Demo03 {
public static void main(String[] args) {
//创建一个Stream流
Stream<String> stream = Stream.of("美羊羊", "喜羊羊", "慢羊羊", "懒羊羊", "沸羊羊", "灰太狼", "红太狼", "小灰灰");
//对Stream流中的元素进行过滤,只要包含"羊羊"
Stream<String> streamYY = stream.filter(s -> s.contains("羊羊"));
//遍历Stream
streamYY.forEach(System.out::println);
}
}
long count()
返回此流中元素的数量。
是一个终结方法,返回值不是Stream,不能再使用Stream中的方法了
作用:统计Stream流中元素的个数
示例:
public class Demo04 {
public static void main(String[] args) {
//创建一个Stream流
Stream<String> stream = Stream.of("美羊羊", "喜羊羊", "慢羊羊", "懒羊羊", "沸羊羊", "灰太狼", "红太狼", "小灰灰");
long count = stream.count();
System.out.println(count);//8
}
}
Stream<T> limit(long maxSize)
返回由此流的元素组成的流,截断长度不超过 maxSize。
作用:获取前几个元素,把元素存储到一个新的Stream流中
例如:
示例:获取Stream流中前5个元素,并遍历
public class Demo05 {
public static void main(String[] args) {
//创建一个Stream流
Stream<String> stream = Stream.of("美羊羊", "喜羊羊", "慢羊羊", "懒羊羊", "沸羊羊", "灰太狼", "红太狼", "小灰灰");
//获取Stream流中的前5个元素
Stream<String> limitStream = stream.limit(5);
//遍历
limitStream.forEach(System.out::println);
}
}
Stream<T> skip(long n)
在丢弃流的第一个 n元素后,返回由此流的其余元素组成的流。
作用:跳过前几个元素,把剩余的元素存储到一个新的Stream流中
例如:skip(3):跳过前三个元素
示例:跳过Stream流的前5个元素,并遍历
public class Demo06 {
public static void main(String[] args) {
//创建一个Stream流
Stream<String> stream = Stream.of("美羊羊", "喜羊羊", "慢羊羊", "懒羊羊", "沸羊羊", "灰太狼", "红太狼", "小灰灰");
//跳过前五个元素
Stream<String> stringStream = stream.skip(5);
//遍历
stringStream.forEach(System.out::println);
}
}
<R> Stream<R> map(Function<? super T,? extends R> mapper)
返回一个流,该流包含将给定函数应用于此流的元素的结果。
参数:函数式接口Function,所以可以使用lambda表达式,重写apply方法
作用:映射,把String流的数据类型转化为另外一种数据类型的Stream流
示例:使用map方法把String类型的Stream映射为Integer类型的Stream
public class Demo07 {
public static void main(String[] args) {
//创建一个Stream流
Stream<String> stringStream = Stream.of("1", "2", "3", "4", "5");
//使用map方法把String类型的Stream映射为Integer类型的Stream
Stream<Integer> integerStream = stringStream.map((String s) -> {
return Integer.parseInt(s);
});
//遍历
integerStream.forEach(System.out::println);
}
}
练习:使用map方法把String类型的姓名映射为Person类型的对象
public class Demo08 {
public static void main(String[] args) {
//创建一个存储String的Stream流
Stream<String> stream = Stream.of("张三", "李四", "王五", "赵六", "田七");
//Stream<Person> personStream = stream.map(name-> new Person(name));
Stream<Person> personStream = stream.map(Person::new);
//遍历
personStream.forEach(System.out::println);
}
}
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
创建一个延迟连接的流,其元素是第一个流的所有元素,后跟第二个流的所有元素。
作用:把两个Stream流合成一个
示例:使用Stream中的静态方法concat,把两个流合成一个新的流
public class Demo09 {
public static void main(String[] args) {
//创建一个Stream1流
Stream<String> stream1 = Stream.of("张三", "李四", "王五", "赵六", "田七");
//创建一个Stream2流
Stream<String> stream2 = Stream.of("美羊羊", "喜羊羊", "慢羊羊", "懒羊羊", "沸羊羊", "灰太狼", "红太狼", "小灰灰");
//使用Stream中的静态方法concat,把两个流合成一个新的流
Stream<String> stream = Stream.concat(stream1, stream2);
//遍历
stream.forEach(System.out::println);
}
}
stream.collect(Collectors.toList());
public class Demo01 {
public static void main(String[] args) {
//创建一个Stream流
Stream<String> stream = Stream.of("美羊羊", "喜羊羊", "慢羊羊", "懒羊羊", "沸羊羊", "灰太狼", "红太狼", "小灰灰");
//转化为List集合:stream.collect(Collectors.toList());
List<String> list = stream.collect(Collectors.toList());
System.out.println(list);
}
}
stream.collect(Collectors.toSet());
public class Demo01 {
public static void main(String[] args) {
//创建一个Stream流
Stream<String> stream = Stream.of("美羊羊", "喜羊羊", "慢羊羊", "懒羊羊", "沸羊羊", "灰太狼", "红太狼", "小灰灰");
Set<String> set = stream.collect(Collectors.toSet());
System.out.println(set);
}
}
转化为数组:stream.toArray()
返回值为Object类型
public class Demo02 {
public static void main(String[] args) {
//创建一个Stream流
Stream<String> stream = Stream.of("美羊羊", "喜羊羊", "慢羊羊", "懒羊羊", "沸羊羊", "灰太狼", "红太狼", "小灰灰");
//使用Stream流中的方法toArray
Object[] arr = stream.toArray();
for (Object o : arr) {
System.out.println(o);
}
}
}
需求:
现在有两个 ArrayList 集合存储队伍当中的多个成员
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!