内部迭代与外部迭代
在介绍Java 8的Stream之前,先介绍一下内部迭代和外部迭代。 外部迭代,顾名思义,就是迭代是发生在Collection外层,由外部程序控制
public class IterationExamples {
public static void main(String[] args){
List<String> alphabets = Arrays.asList(new String[]{"a","b","b","d"});
for(String letter: alphabets){
System.out.println(letter.toUpperCase());
}
}
}
或者直接使用Iterator
public class IterationExamples {
public static void main(String[] args){
List<String> alphabets = Arrays.asList(new String[]{"a","b","b","d"});
Iterator<String> iterator = alphabets.listIterator();
while(iterator.hasNext()){
System.out.println(iterator.next().toUpperCase());
}
}
}
对于内部迭代,表示,迭代完全有Collection内部控制,进行迭代
public class IterationExamples {
public static void main(String[] args){
List<String> alphabets = Arrays.asList(new String[]{"a","b","b","d"});
alphabets.forEach(l -> l.toUpperCase());
}
}
Stream 和 Collection 对比
最基本的一个区别就是,Collection是一个内存数据结构,他会保持当前数据结构所有的值,所以的值都需要处理之后才会加入到Collection中,而Stream概念上是一给固定的数据结构,数据只有在需要的时候才会被处理。 Stream操作要么处于中间过程,要么处于终止状态,对于中间状态,Stream返回其本身,对于终止状态Stream返回一个确定的类型,因此,可以将多个操作构成链式处理。Stream可以线性处理,也可以并行处理。 综上,Stream的主要特点是:
- 并不是数据结构
- 为Lambda设计
- 不支持索引查询
- 可以返回数组或者列表等
- 懒加载
- 容易并行处理
构建Stream
下面介绍各种构建Stream的方法
使用Stream.of(val1,val2,val3...)
public class StreamBuilders {
public static void main(String[] args){
Stream<Integer> stream = Stream.of(1,2,3,4,5,6,7,8,9);
stream.forEach(p -> System.out.println(p));
}
}
使用 Stream.of(arrayOfElements)
public class StreamBuilders {
public static void main(String[] args){
Stream<Integer> stream = Stream.of( new Integer[]{1,2,3,4,5,6,7,8,9} );
stream.forEach(p -> System.out.println(p));
}
}
使用 List.stream()
public class StreamBuilders {
public static void main(String[] args){
List<Integer> list = new ArrayList<Integer>();
for(int i = 1; i< 10; i++){
list.add(i);
}
Stream<Integer> stream = list.stream();
stream.forEach(p -> System.out.println(p));
}
}
使用Stream.generator()
public class StreamBuilders {
public static void main(String[] args){
Stream<Date> stream = Stream.generate(() -> { return new Date();});
stream.forEach(p -> System.out.println(p));
}
}
使用String.chars() 或者 tokens
public class StreamBuilders {
public static void main(String[] args){
IntStream stream = "12345_abcdefg".chars();
stream.forEach(p -> System.out.println(p));
//OR
Stream<String> stream = Stream.of("A$B$C".split("\\$"));
stream.forEach(p -> System.out.println(p));
}
}
将Stream 转换为 Collection
使用Stream.collect(Collecotrs.toList()) 创建List
public class StreamBuilders {
public static void main(String[] args){
List<Integer> list = new ArrayList<Integer>();
for(int i = 1; i< 10; i++){
list.add(i);
}
Stream<Integer> stream = list.stream();
List<Integer> evenNumbersList = stream.filter(i -> i%2 == 0).collect(Collectors.toList());
System.out.print(evenNumbersList);
}
}
使用toArray() 创建数组
public class StreamBuilders {
public static void main(String[] args){
List<Integer> list = new ArrayList<Integer>();
for(int i = 1; i< 10; i++){
list.add(i);
}
Stream<Integer> stream = list.stream();
Integer[] evenNumbersArr = stream.filter(i -> i%2 == 0).toArray(Integer[]::new);
System.out.print(evenNumbersArr);
}
}
Stream 的一些核心操作
示例程序使用下面的List
List<String> memberNames = new ArrayList<>();
memberNames.add("Amitabh");
memberNames.add("Shekhar");
memberNames.add("Aman");
memberNames.add("Rahul");
memberNames.add("Shahrukh");
memberNames.add("Salman");
memberNames.add("Yana");
memberNames.add("Lokesh");
中间操作
中间操作返回的是Stream本身,所以多个中间操作可以作为处理链处理Stream
filter()
filter接受一个Predicate类型,会对stream中所有元素进行过滤。
memberNames.stream().filter((s) -> s.startsWith("A"))
.forEach(System.out::println);
map()
map() 将Stream中的元素从一种形式转化为另一种形式
memberNames.stream().filter((s) -> s.startsWith("A"))
.map(String::toUpperCase)
.forEach(System.out::println);
sorted()
sorted() 返回一个排序的Stream 视图,sorted() 默认自然排序,同时也可以定制Comparator
memberNames.stream().sorted()
.map(String::toUpperCase)
.forEach(System.out::println);
终止操作
终止操作会返回一个特定的类型,而不是返回Stream本身。
foreach()
其作用是便利stream所有的元素
memberNames.forEach(System.out::println);
collect()
collect() 收集stream中的元素转化为collection
List<String> memNamesInUppercase = memberNames.stream().sorted()
.map(String::toUpperCase)
.collect(Collectors.toList());
match()
match() 方法是用来判断Stream中的某个元素是否符合某项断言
boolean matchedResult = memberNames.stream()
.anyMatch((s) -> s.startsWith("A"));
System.out.println(matchedResult);
matchedResult = memberNames.stream()
.allMatch((s) -> s.startsWith("A"));
System.out.println(matchedResult);
matchedResult = memberNames.stream()
.noneMatch((s) -> s.startsWith("A"));
count()
统计stream的元素个数,返回long
long totalMatched = memberNames.stream()
.filter((s) -> s.startsWith("A"))
.count();
reduce()
对Stream中的元素做归约操作,返回一个Optional的值
Optional<String> reduced = memberNames.stream()
.reduce((s1,s2) -> s1 + "#" + s2);
并行
对于Stream来说实现并行非常的简单,只需要将stream() 修改为 parallelStream即可,其底层采用了Fork/Join框架实现并行。
class StreamBuilders {
public static void main(String[] args){
List<Integer> list = new ArrayList<Integer>();
for(int i = 1; i< 10; i++){
list.add(i);
}
//Here creating a parallel stream
Stream<Integer> stream = list.parallelStream();
Integer[] evenNumbersArr = stream.filter(i -> i%2 == 0).toArray(Integer[]::new);
System.out.print(evenNumbersArr);
}
}