Java 8 基础教程 - Stream

951 阅读4分钟
原文链接: www.codemore.top
内部迭代与外部迭代

在介绍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);
     }
}