Java8更新之后提供了Stream流,为了让代码更加简洁,所以学习Stream流很有必要,本文为作者学习Stream流的笔记,仅此记录。
java.util.stream.Stream 是Java 8新加入的最常用的流接口。(这并不是一个函数式接口。)获取一个流非常简单,有以下几种常用的方式:所有的 Collection 集合都可以通过 stream 默认方法获取流;Stream 接口的静态方法 of 可以获取数组对应的流。
Collection包含List和Set,两者获取流的方式相似。
List<String> list = new ArrayLise<>();
Stream<String> streamList = list.stream();
Set<String> set= new HashMap<>();
Stream<String> streamSet = set.stream();
java.util.Map不是Collection的接口 ,Map是包含<K,V>键值对的。所以要根据Key和Value分别获取Stream
Stream keyStream = map.keySet.Stream();
Stream valueStream = map.values.Stream();
Map<Map.Entry<String,String>> entryStream = map.entrySet.Stream();
String[] array = { "张三","张四" ,"王五"};
Strean<String> stream = stream.of(array);
Stream操作大体上可以分为三类
void forEach(Consumer<? super T> action);
该方法接受一个Consumer接口函数(说明该方法支持lambda函数或引用),将每一个流元素交给该函数处理,类似于遍历。
private static void forEachDemo(){
Stream<String> stream = Stream.of(array);
stream.forEach(s-> System.out.println(s));
}
输出结果:
张三
张四
王五
Stream<T> filter(Predicate<? super T> predicate);
该接口接收一个 Predicate 函数式接口参数(可以是一个Lambda或方法引用)作为筛选条件。
Stream<String> stream = Stream.of(array);
stream.filter(s->s.startsWith("张"))
.forEach(System.out::println);
输出结果:
张三
张四
该接口需要一个 Function 函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。
List<Integer> list = new ArrayList<Integer>(){{
add(1);
add(2);
add(3);
}};
list.stream().map(s->s.toString()).forEach(System.out::println);
输出结果:
1
2
3
当然,这个作用不仅是转换类型。
count方法类似于Collection中的size方法一样,提供元素个数:
long count();
需要注意的是返回的是一个 long
类型的的返回值(而非int
类型)。
public static final void countDemo(){
Stream<String> stream = Stream.of(array);
System.out.println(stream.count());
}
输出结果
3
limit 方法可以对流进行截取,只取用前n个。
Stream<T> limit(long maxSize);
如果截取长度大于数组长度,则不进行操作
private static void limitDemo(){
Stream<String> stream = Stream.of(array);
Arrays.stream(array)
.limit(2)
.forEach(System.out::println);
}
输出结果:
张三
张四
跳过前几个元素,可以使用 skip 方法获取一个截取之后的新流:
Stream<T> skip(long n);
需要注意的是:
如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流。
n必须大于等于0,如果大于当前流中的元素个数,则产生一个空流。
private static void skipDemo(){
Arrays.stream(array)
.skip(2)
.forEach(System.out::println);
}
输出结果:
王五
如果有两个流,希望合并成为一个流,那么可以使用 Stream 接口的静态方法 concat :
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
private static void concatDemo(){
Stream<String> stream1 = Stream.of("张三");
Stream<String> stream2 = Stream.of("李四");
Stream<String> stream = Stream.concat(stream1,stream2);
stream.forEach(System.out::println);
}
输出结果:
张三
李四
Stream<T> sorted()
sorted 方法用于对流进行排序。
例子简单,待补充。
Stream<T> sorted()
流对象.collect( Collectors.toList() )
获得List集合。
流对象.collect( Collectors.toSet() )
获得Set集合。
流对象. toArray()
由于泛型擦除的原因,返回值类型是Object[]
groupingBy()方法是Collectors类中的静态方法
public static <T, K, A, D>
Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
Collector<? super T, A, D> downstream)
例子
//统计数组中出现单词个数
private static void groupingByDemo(){
List<String> items = Arrays.asList("apple", "apple", "banana", "apple", "orange", "banana", "papaya");
Map<String, Long> result = items.stream()
.collect(Collectors.groupingBy(
Function.identity(),Collectors.counting()
));
result.forEach((o1,o2)-> System.out.println(o1 + ":" + o2));
}
其中 Function.identity()
可以替换为t->t
,Collectors.counting()
为统计流中出现次数。
输出结果:
papaya:1
orange:1
banana:2
apple:3
public static <T>
Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate)
类似于分组,将符合条件的分为一组,不符合条件的分为一组。
private static void partitioningByDemo(){
System.out.println(Arrays.stream(array).collect(Collectors.partitioningBy(s -> s.startsWith("张"))));
}
输出结果:
{false=[王五], true=[张三, 张四]}
allMatch(Predicate<? super T> predicate)
用于检测是否全部都满足指定的参数行为,如果全部满足则返回true
anyMatch(Predicate<? super T> predicate)
anyMatch则是检测是否存在一个或多个满足指定的参数行为,如果满足则返回true
noneMatch(Predicate<? super T> predicate)
oneMatch用于检测是否不存在满足指定行为的元素,如果不存在则返回true
findFirst()
findFirst用于返回满足条件的第一个元素
findAny()
findAny相对于findFirst的区别在于,findAny不一定返回第一个,而是返回任意一个
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter)
参数为连接符,返回值为一个集合。
private static void joinDemo(){
System.out.println(Arrays.stream(array).collect(Collectors.joining(",")));
}
输出结果:
张三,张四,王五