一.练习(体验Stream流的作用)
需求:
按照下面的要求完成集合的创建和遍历
创建一个集合,存储多个字符元素
(1).把所有以“张”开头的元素存储到新集合中
(2).把“张”开头的,长度为3的元素存储到新集合中
(3).遍历打印最终结果
(没有使用Stream流的效果)
import java.util.ArrayList;
public class Stream {
public static void main(String[] args) {
ArrayList<String> list1 = new ArrayList<>();
list1.add("张无忌");
list1.add("周芷若");
list1.add("赵敏");
list1.add("张强");
list1.add("张三丰");
ArrayList<String> list2 = new ArrayList<>();
for (String string : list1) {
if (string.startsWith("张")) {
list2.add(string);
}
}
ArrayList<String> list3 = new ArrayList<>();
for (String string : list2) {
if (string.length() == 3) {
list3.add(string);
}
}
for (String string : list3) {
System.out.println(string);
}
}
}
(使用Stream流之后的效果)
import java.util.ArrayList;
public class Stream {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
list.stream().filter(name -> name.startsWith("张")).filter(name -> name.length() == 3).forEach(name -> System.out.println(name));
}
}
二.Stream流
1.思想:
对Stream流按照需求进行过滤操作,之后输出符合要求的数据
2.作用:
结合了Lambda表达式,简化集合,数组的操作
3.使用步骤
(1).先得到一条Stream流(流水线),并把数据放到这个流水线中
获取方式:
使用单列集合的形式,利用Collection中的默认方法default Stream<E> stream()
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Consumer;
import java.util.stream.Stream;
public class stream {
public static void main(String[] args) {
//单列集合
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "a", "b", "c", "d", "e");
//获取到一条流水线,并把集合中的所有数据放到流水线上
Stream<String> stream1 = list.stream();
//使用终结方法打印流水线上的所有数据
stream1.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
//Lambda表达式
list.stream().forEach(s -> System.out.println(s));
}
}
使用双列集合无法直接使用Stream流
import java.util.HashMap;
public class stream {
public static void main(String[] args) {
//双列集合(无法直接使用Stream流),使用单列集合进行转换
HashMap<String, Integer> hm = new HashMap<>();
hm.put("a", 1);
hm.put("b", 2);
hm.put("c", 3);
hm.put("d", 4);
//只能获取到键的Stream流
hm.keySet().stream().forEach(s -> System.out.println(s));
//直接获取键值对的Stream流
hm.entrySet().stream().forEach(s -> System.out.println(s));
}
}
使用数组时,利用Arrays工具类中的静态方法public static<T> Stream<T> stream(T[] array)
import java.util.Arrays;
public class stream {
public static void main(String[] args) {
//数组
int[] arr1 = {1, 2, 3, 4, 5, 6, 7, 8};
String[] arr2 = {"a", "b", "c"};
Arrays.stream(arr1).forEach(s -> System.out.println(s));
Arrays.stream(arr2).forEach(s -> System.out.println(s));
}
}
在使用一堆零散数据时,使用Stream接口中的静态方法public static<T> Stream<T> of(T...values)
import java.util.stream.Stream;
public class stream {
public static void main(String[] args) {
//一堆零散数据
//基本数据类型
Stream.of(1, 2, 3, 4, 5).forEach(s -> System.out.println(s));
//引用数据类型
Stream.of("a", "b", "c", "d", "e").forEach(s -> System.out.println(s));
}
}
注意点:最好不要使用将数据存入数组之后再使用Stream.of方法使用Stream流的方式输出数据的方式,如果是存入的基本数据类型,那么输出的就会是整个数组的地址值
(2).使用中间方法对流水线上的数据进行操作
Stream<T> filter(Predicate<? super T>predicate)过滤
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class stream {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张三丰", "张翠山", "张良", "王二", "谢广坤");
list.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.startsWith("张");
}
}).forEach(s -> System.out.println(s));
//Lambda表达式(链式编程)
list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s));
//非链式编程
Stream<String> stream1 = list.stream().filter(s -> s.startsWith("张"));
Stream<String> stream2 = stream1.filter(s -> s.length() == 3);
stream2.forEach(s -> System.out.println(s));
//虽然非链式编程一直到这里都是能正常编译的,但是到下一步就会因为stream1已经被stream2使用过一次而关闭,因此使用不了
//Stream<String> stream3=stream1.filter(s->s.length()==3);
//修改Stream流中的数据不会影响到原本的数据,因此在下方打印list仍然会是一开始输入到list中的完整的数据
System.out.println(list);
}
}
Stream<T> limit(long maxSize)获取前几个元素
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;
public class stream {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张三丰", "张翠山", "张良", "王二", "谢广坤");
//使用limit方法获取了前三个元素,因此输出的结果是张无忌,周芷若,赵敏
Stream<String> stream = list.stream().limit(3);
stream.forEach(s -> System.out.println(s));
}
}
Stream<T> skip(long n)跳过前几个元素
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;
public class stream {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张三丰", "张翠山", "张良", "王二", "谢广坤");
//跳过了前三个元素,因此输出的结果为张三丰,张翠山,张良,王二,谢广坤
Stream<String> stream = list.stream().skip(3);
stream.forEach(s -> System.out.println(s));
}
}
Stream<T> distinct()元素去重,依赖(hashCode和equals方法)
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;
public class stream {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "张无忌", "周芷若", "赵敏", "张三丰", "张翠山", "张良", "王二", "谢广坤");
//去除了重复的张无忌元素,因此输出的结果中会少一个张无忌
Stream<String> stream = list.stream().distinct();
stream.forEach(s -> System.out.println(s));
}
}
static<T> Stream<T> concat(Stream a,Stream b)合并a和b两个Stream流为一个
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;
public class stream {
public static void main(String[] args) {
ArrayList<String> list1 = new ArrayList<>();
ArrayList<String> list2 = new ArrayList<>();
Collections.addAll(list1, "张无忌", "张无忌", "周芷若");
Collections.addAll(list2, "赵敏", "张三丰", "张翠山", "张良", "王二", "谢广坤");
Stream<String> stream1 = list1.stream();
Stream<String> stream2 = list2.stream();
//通过concat方法将两个Stream流进行了合并,最后输出的数据是stream1和stream2中所存储的全部的数据
Stream<String> stream3 = Stream.concat(stream1, stream2);
stream3.forEach(s -> System.out.println(s));
}
}
Stream<R> map(Function<T, R> mapper)转换流中的数据类型
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
public class stream {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌-1", "周芷若-2", "赵敏-3", "张三丰-4", "张翠山-5", "张良-6", "王二-7", "谢广坤-8");
//需求:只获取里面的数字数据并进行打印
list.stream().map(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
String[] arr = s.split("-");
String numberString = arr[1];
int number = Integer.parseInt(numberString);
return number;
}
}).forEach(s -> System.out.println(s));
//Lambda表达式
list.stream().map(s -> Integer.parseInt(s.split("-")[1])).forEach(s -> System.out.println(s));
}
}
注意点1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,所以建议使用链式编程
注意点2:修改Stream流中的数据,不会影响原来集合或者数组中的数据
(3).使用终结方法对流水线上的数据进行操作
终结方法:
void forEach(Consumer action)遍历
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Consumer;
public class stream {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张三丰", "张翠山", "张良", "王二", "谢广坤");
list.stream().forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
//Lambda表达式
list.stream().forEach(s -> System.out.println(s));
}
}
long count()统计
import java.util.ArrayList;
import java.util.Collections;
public class stream {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张三丰", "张翠山", "张良", "王二", "谢广坤");
//使用count方法对list中的元素进行计数,最终得出的结果为8
long count = list.stream().count();
System.out.println(count);
}
}
toArray()收集流中的数据,放到数组中
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.IntFunction;
public class stream {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张三丰", "张翠山", "张良", "王二", "谢广坤");
//空参构造的toArray方法
Object[] array = list.stream().toArray();
System.out.println(Arrays.toString(array));
//带有参数的toArray方法
//InFunction的泛型:具体类型的数组
//apply的形参:流中数据的个数
//apply的返回值:具体类型的数组
String[] array1 = list.stream().toArray(new IntFunction<String[]>() {
@Override
public String[] apply(int value) {
return new String[value];
}
});
System.out.println(Arrays.toString(array1));
//Lambda表达式
String[] array2=list.stream().toArray(value -> new String[value]);
System.out.println(Arrays.toString(array2));
}
}
collect(Collector collector)收集流中的数据,放到集合中
有关collect方法的详解请看:
https://blog.csdn.net/NaZiMeKiY/article/details/137685709
三.总结
1.Stream流的作用
结合了Lambda表达式,简化集合和数组的操作
2.Stream的使用步骤
(1).获取Stream流对象
(2).使用中间方法处理数据
(3).使用终结方法处理数据
3.如何获取Stream流对象
(1).单列集合:Collection中的默认方法stream
(2).双列集合:不能直接获取
(3).数组:Arrays工具类型中的静态方法stream
(4).一堆零散的数据:Stream接口中的静态方法of
4.常见方法
中间方法:filter,limit,skip,distinct,concat,map
终结方法:forEach,count,collect