Java Stream API

[TOC]

Java8 中 的Steam 可以定义为来自来源的元素序列,Streams支持对元素进行聚合操作,这里的元素指的是为流提供数据的集合和 数组,在聚合操作中我们可以根据我们需求来获取出符合我们要求的数据

在操作Stream 流之前我们应该知道,Streams API 都是直接针对流的操作,因此首先我们要先会创建一个 Steam。

在粒度级别,Collection 和 Stream 之间的区别与计算事物的时间有关。甲Collection是一个存储器内数据结构,其中认为所述数据结构当前具有的所有值。必须先计算集合中的每个元素,然后才能将其添加到集合中。Stream 在概念上是一个管道,其中元素是按需计算的。

这个概念带来了显着的编程优势。这个想法是,用户将仅从 Stream 中提取他们需要的值,并且这些元素仅在需要时(对用户不可见)生成。这是生产者-消费者关系的一种形式。

在 Java 中,java.util.Stream表示可以对其执行一个或多个操作的流。流操作要么是中间的,要么是终端的。

终端操作返回一个特定类型的结果和中间操作返回流本身,所以我们可以连锁的一排的多个方法,以在多个步骤中执行该操作。

流是在源上创建的,例如java.util.Collection喜欢ListSet。在Map不直接支持,我们可以创建映射键,值。

流操作可以顺序或并行执行。当并行执行时,它被称为并行流

1. 创建流

下面给出了一些创建流的方式

1.1 Stream.of()
 public static void main(String[] args)
     {
         // 通过Stream.of 方法获取一个数据流
         Stream<Integer> stream = Stream.of(1,2,3,4,5,6,7,8,9);
         stream.forEach(p -> System.out.println(p));
     }
1.2 Stream.of(数组)

我们可以通过引入一个数组的方式生成一个流

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));
     }
1.3 列表.steam( 常用)

工作中我们经常使用通过一个集合来获取一个流,流中的元素都是来自List

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));
     }
1.4 Stream.generate() 或者 Stream.iterate()

// 下面的代码中,我们从给的元素中创建一个流,但是我们只是限制去获取 20 个,因此我们用 limit 进行限制

 public static void main(String[] args)
     {
         Stream<Integer> randomNumbers = Stream
             .generate(() -> (new Random()).nextInt(100));

         randomNumbers.limit(20)
              .forEach(System.out::println);
     }

1.5 字符串字符流

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));
     

1.6 Stream.builder()

通过创建一个builder 方法创建一个建造器,同样生成流

Stream<Object> name = Stream.builder().add("name").build();

2. Stream Collector(流收集器)

在对流中的元素执行中间件操作后,我们可以 使用流收集器方法再次将处理过的元素收集到一个集合中

2.1 将stream中的元素收集到一个集合中

在给定的例子中,首先,我们在整数 1 到 10 上创建一个流。然后我们处理流元素以找到所有偶数.最后将所有的偶数收集到一个集合中

 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);
     }
2.2 将stream 中元素收集到数组中

和上一个实例中的需求一样,这次我们是将偶数收集到一个数组中

List<Integer> result = new ArrayList<>();
        for (Integer x : list) {
            if (x % 2 == 0) {
                result.add(x);
            }
        }

Integer[] evenNumbersArr = list.stream().filter(x -> x% 2 == 0).toArray(Integer[]::new);


3. 流操作

  • 中间流操作 操作之后返回的还是一个Steam 流,
  • 终端操作 操作之后直接对六中的数据进行处理,没有返回值

    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");
3.1.1 Stream.filter (过滤)
 过滤操作接收了一个Predicate 类型的方法, 返回一个 符合 predicate  要求的steam 流,比如从以上的集合中获取 是 A 开头的城市
memberNames.stream().filter((s) -> s.startsWith("A"))                    .forEach(System.out::println);
3.1.2 Stream.map (转换,映射)

map 操作 我认为是一种转换或者映射的操作,例如 我们将集合中的小写 字符都转变成大写字符

memberNames.stream().filter((s) -> s.startsWith("A"))                    .map(String::toUpperCase)                    .forEach(System.out::println);
3.1.3 Stream.sorted (排序)

排序接口可以直接对集合中的元素进行排序, 在java 8 之前我们要对list 中的元素进行排序,我们可能比较复杂,要用 sort方法,并用Compare 匿名内部类,写法比较繁琐

memberNames.sort(new Comparator<String>() {            @Override            public int compare(String o1, String o2) {                return 0;            }        });

但是 现在使用java 8 之后,我们可以用另一种方式,进行排序

memberNames.stream().sorted()                    .map(String::toUpperCase)                    .forEach(System.out::println);

这种方式默认的方式是正向排序,如果想反向排序,可以使用 reverse 方法进行改变顺序

3.2 终端操作

终端操作会返回终端操作的结果,

3.2.1 Stream.foreach

foreach 是一个遍历迭代的功能

memberNames.forEach(System.out::println);
3.2.2 collect 收集

collect 是一个收集的方法,从Stream 中获取符合的数据 然后储存到一个集合中

List<String> memNamesInUppercase = memberNames.stream().sorted()                            .map(String::toUpperCase)                            .collect(Collectors.toList());         System.out.print(memNamesInUppercase);
3.2.3 match 匹配

match 是 我针对match 类方法的一种统称,和 之前讲的filter 差不多,但是功能上稍微强大一些,而且方法比较多

//只要 元素中 有一个符合  是A 开始的就返回Trueboolean matchedResult = memberNames.stream()        .anyMatch((s) -> s.startsWith("A")); System.out.println(matchedResult); // 如果元素全部是用A开头的,那么返回TruematchedResult = memberNames.stream()        .allMatch((s) -> s.startsWith("A")); System.out.println(matchedResult); //如果元素没有用A 开头的,返回truematchedResult = memberNames.stream()        .noneMatch((s) -> s.startsWith("A")); System.out.println(matchedResult);
4.2.4. Stream.count ()

计数的一个终端操作,返回一个long 型的 返回值

long totalMatched = memberNames.stream()    .filter((s) -> s.startsWith("A"))    .count(); System.out.println(totalMatched);
4.2.5. Stream.reduce ()

reduce 原意 减少,缩小 ,根据指定的计算模型将stream中的值计算到一个最终结果,

针对这个方法有一个博主文章将的特别好,在此借鉴一下 java8 reduce

总结 针对stream 常用操作方法进行了记录

中间操作

  • filter
  • map
  • distinct
  • sorted
  • peek
  • limit
  • skip

终端操作

  • foreach
  • toArray
  • reduce
  • foreachOrdered
  • min
  • max
  • count
  • anyMatch
  • collect
  • findfirst 等
03-05 15:01