Java 8 中,得益于 lambda
带来的函数式编程,引入了一个全新的 Stream流
概念,用于解决集合已有的弊端。
我们先来看一个例子:
筛选出 names 中以 '张' 开头的字符串得到子集1,再筛选出 子集1 中长度为 3 的字符串,然后遍历输出。
// 传统集合的方式 public static void main(String[] args) { List<String> names = new ArrayList<>(); names.add("张三丰"); names.add("张大宝"); names.add("张三"); names.add("德玛杰"); names.add("乔峰"); names.add("李大宝"); List<String> list1 = new ArrayList<>(); //以 '张' 开头的字符串 for (String name:names){ if (name.startsWith("张")){ list1.add(name); } } List<String> list2 = new ArrayList<>(); // list1中长度为 3 的字符串 for (String name:list1){ if (name.length()==3){ list2.add(name); } } for (String name:list2){ System.out.println(name); } } 复制代码
// stream流方式 public static void main(String[] args) { List<String> names = new ArrayList<>(); names.add("张三丰"); names.add("张大宝"); names.add("张三"); names.add("德玛杰"); names.add("乔峰"); names.add("李大宝"); names.stream().filter(name->name.startsWith("张")) .filter(name->name.length()==3).forEach(System.out::println); } 复制代码
可以看到用 stream
流方式比传统集合的方式精简了很多。
Collection
集合可以通过 stream()
方法获取流. Stream
类的静态方法 of()
通常用于将数组转成 stream
流。 public static void main(String[] args) { // 集合转成 stream 流 List<String> list = new ArrayList<>(); Stream<String> listStream = list.stream(); Set<Integer> set = new HashSet<>(); Stream<Integer> setStream = set.stream(); // 数组转成 stream 流 String[] names = new String[]{"zs","ls","ww"}; Stream<String> namesStream = Stream.of(names); Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5); } 复制代码
stream
流中方法分为两类:
Stream
类型 Stream
类型,例如: count()
和 forEach()
。 filter()
将一个流转换成另外一个子流,该方法接受一个 Predicate 类型的参数
(系统内置函数接口之一)。
Stream<T> filter(Predicate<? super T> predicate);
public static void main(String[] args) { List<String> names = new ArrayList<>(); names.add("张三丰"); names.add("张大宝"); names.add("张三"); names.add("德玛杰"); names.add("乔峰"); names.add("李大宝"); // 过滤 names 集合,只要姓张的人,然后输出 names.stream().filter(name->name.startsWith("张")). forEach(System.out::println); } 复制代码
Stream
流属于管道流, 只能被使用一次 ,当一个 Stream
流调用了终结方法后,就会被关闭, 再次调用其方法会报错 。
public static void main(String[] args) { // 数组转成 stream 流 String[] names = new String[]{"zsf","ls","ww"}; Stream<String> namesStream = Stream.of(names); namesStream.filter(name->name.length()==3). forEach(System.out::println); // 流已经被关闭,再次调用 namesStream.forEach(System.out::println); } 复制代码
如果需要将流中的元素映射到另一个流中,可以用 map()
方法,一般用于将一种类型的数据转成另一种类型的数据。
<R> Stream<R> map(Function<? super T, ? extends R> mapper); 复制代码
public static void main(String[] args) { // 数组转成 stream 流 String[] strings = new String[]{"1","2","3"}; Stream<String> stream1 = Stream.of(strings); // 使用 map 方法,将字符串类型的整数转成 Integer 类型的整数,然后遍历 Stream<Integer> stream2 = stream1.map(k->Integer.parseInt(k)); stream2.forEach(System.out::println); } 复制代码
limit()
可以对流中的元素进行截取,只截取前 n 个
public static void main(String[] args) { // 数组转成 stream 流 String[] strings = new String[]{"1","2","3","4"}; // 只截取前3个元素,输出 Stream.of(strings).limit(3).forEach(System.out::println); } 复制代码
跳过流中的前 n 个元素,如果 n 大于流中元素的个数,返回一个长度为 0 的流。
public static void main(String[] args) { // 数组转成 stream 流 String[] strings = new String[]{"1","2","3","4"}; // 跳过前2个元素,输出 Stream.of(strings).skip(2).forEach(System.out::println); } 复制代码
Stream
类的静态方法用于将两个流合并。
public static void main(String[] args) { // 数组转成 stream 流 String[] strings1 = new String[]{"1","2","3","4"}; String[] strings2 = new String[]{"3","4","5","6"}; Stream<String> stream1 = Stream.of(strings1); Stream<String> stream2 = Stream.of(strings2); Stream<String> stream3 = Stream.concat(stream1,stream2); stream3.forEach(System.out::println); // 输出 1,2,3,4,3,4,5,6 } 复制代码