目录
一、获取流
java.util.stream.Stream<T> 是Java 8新加入的最常用的流接口。(这并不是一个函数式接口。)
获取一个流非常简单,有以下几种常用的方式:
(1)所有的Collection 集合都可以通过stream 默认方法获取流;
(2)Stream 接口的静态方法of 可以获取数组对应的流。
1.根据Collection获取流
java.util.Collection 接口中加入了default方法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();
2.根据Map获取流
java.util.Map 接口不是Collection 的子接口,且其K-V数据结构不符合流元素的单一特征,所以获取对应的流需要分key、value或entry等情况:
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();
3.根据数组获取流
如果使用的不是集合或映射而是数组,由于数组对象不可能添加默认方法,所以Stream 接口中提供了静态方法of。
String[] array = { "张无忌", "张翠山", "张三丰", "张一元" };
Stream<String> stream = Stream.of(array);
二.常用方法
流模型的方法被分成两种:
终结方法:返回值类型不再是Stream接口自身类型的方法,不支持链式调用
非终结方法:返回值类型仍然是Stream接口的方法,支持链式调用
1.过滤:filter
Stream<T> filter(Predicate<? super T> predicate);
2.统计个数:count
long count();
3.取用前几个:limit
Stream<T> limit(long maxSize);
4.跳过前几个:skip
Stream<T> skip(long n);
5.映射:map
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
该接口需要一个Function 函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。
6.组合:concat
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
7.逐一处理:forEach
void forEach(Consumer<? super T> action);
三、常用方法综合案例
现在有两个ArrayList 集合存储队伍当中的多个成员姓名,要求使用传统的for循环(或增强for循环)依次进行以
下若干操作步骤:
1. 第一个队伍只要名字为3个字的成员姓名;
2. 第一个队伍筛选之后只要前3个人;
3. 第二个队伍只要姓张的成员姓名;
4. 第二个队伍筛选之后不要前2个人;
5. 将两个队伍合并为一个队伍;
6. 根据姓名创建Person 对象;
7. 打印整个队伍的Person对象信息。
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("张三");
// 第一个队伍只要名字为3个字的成员姓名;
// 第一个队伍筛选之后只要前3个人;
Stream<String> streamOne = one.stream().filter(s -> s.length() == 3).limit(3);
// 第二个队伍只要姓张的成员姓名;
// 第二个队伍筛选之后不要前2个人;
Stream<String> streamTwo = two.stream().filter(s -> s.startsWith("张")).skip(2);
// 将两个队伍合并为一个队伍;
// 根据姓名创建Person对象;
// 打印整个队伍的Person对象信息。
Stream.concat(streamOne, streamTwo).map(Person::new).forEach(System.out::println);
四、函数拼接与终结方法
五、收集Stream结果
1.Stream转集合
Stream流提供collect 方法,其参数需要一个java.util.stream.Collector<T,A, R> 接口对象来指定收集到哪种集合中。幸运的是, java.util.stream.Collectors 类提供一些方法,可以作为Collector 接口的实例:
public static <T> Collector<T, ?, List<T>> toList() :转换为List 集合。
public static <T> Collector<T, ?, Set<T>> toSet() :转换为Set 集合。
Stream<String> stream = Stream.of("10", "20", "30", "40", "50");
List<String> list = stream.collect(Collectors.toList());
Stream<String> stream1 = Stream.of("10", "20", "30", "40", "50");
Set<String> set = stream1.collect(Collectors.toSet());
2.Stream转数组
Stream提供toArray 方法来将结果放到一个数组中,由于泛型擦除的原因,返回值类型是Object[]的:
Object[] toArray();
Stream<String> stream3= Stream.of("10", "20", "30", "40", "50");
Object[] objArray = stream3.toArray();
3.Stream转数组方式二
有了Lambda和方法引用之后,可以使用toArray 方法的另一种重载形式传递一个IntFunction<A[]> 的函数,继
而从外面指定泛型参数。方法签名:
<A> A[] toArray(IntFunction<A[]> generator);
Stream<String> stream4 = Stream.of("10", "20", "30", "40", "50");
String[] strArray = stream4.toArray(String[]::new);