内部迭代与外部迭代
在介绍 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);
- }
- }
来源: https://juejin.im/entry/5af19766518825673447002c