P16-18
程序清单1-4 collecting/CollectingResults.java


  1. 代码
  2. 项目结构
  3. 分析
  4. 重要API

1.代码

import java.io.*;
import java.nio.charset.*;
import java.nio.file.*;
import java.util.*;
import java.util.stream.*;

public class CollectingResults
{
   public static Stream<String> noVowels() throws IOException
   {
   //读取alice30.txt文件中所有内容并赋给contents字符串
      String contents = new String(Files.readAllBytes(
            Paths.get("../gutenberg/alice30.txt")),
            StandardCharsets.UTF_8);

   //将contents中字符串切割成单词并存入wordList列表
      List<String> wordList = Arrays.asList(contents.split("\\PL+"));

    //创建wordList列表对应的流并赋给words字符串流
      Stream<String> words = wordList.stream();

    //将words映射为一个“将元音字母全部改为空”的字符串流stream并返回
      return words.map(s -> s.replaceAll("[aeiouAEIOU]", ""));
   }

   public static <T> void show(String label, Set<T> set)
   {
   //打印set所属类型
      System.out.print(label + ": " + set.getClass().getName());

    //打印set对应流的元素(以逗号分隔)
      System.out.println("["
            + set.stream().limit(10).map(Object::toString)
                  .collect(Collectors.joining(", ")) + "]");
   }

   public static void main(String[] args) throws IOException
   {
   //迭代遍历流里前十个元素并打印。从0开始,每次加1
      Iterator<Integer> iter = Stream.iterate(0, n -> n + 1).limit(10)
            .iterator();
      while (iter.hasNext())
         System.out.println(iter.next());

    //迭代流里前十个元素并赋给object数组numbers,打印数组首地址
      Object[] numbers = Stream.iterate(0, n -> n + 1).limit(10).toArray();
      System.out.println("Object array:" + numbers); // Note it's an Object[] array

      try
      {
      //打印numbers数组的第一个元素
         Integer number = (Integer) numbers[0]; // OK
         System.out.println("number: " + number);

         System.out.println("The following statement throws an exception:");
         Integer[] numbers2 = (Integer[]) numbers; // Throws exception
      }
      catch (ClassCastException ex)
      {
      //打印异常信息
         System.out.println(ex);
      }

    //迭代并构造流里前十个元素赋给Integer数组numbers,打印数组首地址
      Integer[] numbers3 = Stream.iterate(0, n -> n + 1).limit(10)
         .toArray(Integer[]::new);
      System.out.println("Integer array: " + numbers3); // Note it's an Integer[] array

      Set<String> noVowelSet = noVowels()
            .collect(Collectors.toSet());
      show("noVowelSet", noVowelSet);

      TreeSet<String> noVowelTreeSet = noVowels().collect(
            Collectors.toCollection(TreeSet::new));
      show("noVowelTreeSet", noVowelTreeSet);

      String result = noVowels().limit(10).collect(
            Collectors.joining());
      System.out.println("Joining: " + result);
      result = noVowels().limit(10)
            .collect(Collectors.joining(", "));
      System.out.println("Joining with commas: " + result);

      IntSummaryStatistics summary = noVowels().collect(
            Collectors.summarizingInt(String::length));
      double averageWordLength = summary.getAverage();
      double maxWordLength = summary.getMax();
      System.out.println("Average word length: " + averageWordLength);
      System.out.println("Max word length: " + maxWordLength);
      System.out.println("forEach:");
      noVowels().limit(10).forEach(System.out::println);
   }
}

alice30.txt在这里就不贴出了,读者可以自己随意写个文本文档进行测试。

2.项目结构

这里写图片描述

3.分析

先讲一下两个静态方法


public static Stream<String> noVowels() throws IOException
   {
      String contents = new String(Files.readAllBytes(
            Paths.get("../gutenberg/alice30.txt")),
            StandardCharsets.UTF_8);
      List<String> wordList = Arrays.asList(contents.split("\\PL+"));
      Stream<String> words = wordList.stream();
      return words.map(s -> s.replaceAll("[aeiouAEIOU]", ""));
   }

noVowels()方法:从alice30.txt中读取字符内容,分隔为单词并去除元音字母后返回流Stream<String>
words.map(s -> s.replaceAll("[aeiouAEIOU]", ""))将words中的元素一一映射为新的元素,并整合为新流。[aeiouAEIOU]是正则表达式,匹配元音字母。


public static <T> void show(String label, Set<T> set)
   {
      System.out.print(label + ": " + set.getClass().getName());
      System.out.println("["
            + set.stream().limit(10).map(Object::toString)
                  .collect(Collectors.joining(", ")) + "]");
   }

show(String label, Set<T> set)方法:打印label,打印set中前十个元素(以逗号分隔)。
getClass()getName()利用反射机制,是Object方法。
collect(Collectors.joining(", "))方法:收集流中的元素并以逗号分隔,返回String类型。


回到main函数


以下:

try
      {
         Integer number = (Integer) numbers[0]; // OK
         System.out.println("number: " + number);
         System.out.println("The following statement throws an exception:");
         Integer[] numbers2 = (Integer[]) numbers; // Throws exception
      }
      catch (ClassCastException ex)
      {
         System.out.println(ex);
      }

这里解释一下这句代码:Integer[] numbers2 = (Integer[]) numbers; // Throws exception
numbers是Object数组对象,而Object[]并不是Integer[]的父类,因此强制转型后抛出ClassCastException类型匹配异常。
main函数其余部分,请参照重要API佐证理解。

4.重要API

java.util.stream.BaseStream 8


Iterator<T> iterator()
产生一个用于获取当前流中各个元素的迭代器。这是一种终结操作。


java.util.stream.BaseStream 8


Iterator<T> iterator()
产生一个用于获取当前流中各个元素的迭代器。这是一种终结操作。


java.util.stream.Stream 8


void forEach(Consumer<? super T>action)
在流的每个元素上调用action。这是一种终结操作。

Object[] toArray()
<A>A[] toArray(IntFunction<A[]> generator)
产生一个对象数组,或者在将引用A[]::new传递给构造器时,返回一个A类型的数组。这些操作都是终结操作。

<R,A> R collect(Collector<? super T,A,R> collector)
使用给定的收集器来收集当前流中的元素。Collectors类有用于多种收集器的工厂方法。


java.util.stream.Collectors 8


static <T> Collector<T,?,List<T>> toList()
static <T> Collector<T,?,Set<T>> toSet()
产生一个将元素收集到列表或集中的收集器。

static <T,C extends Collection<T>> Collector<T,?,C> toCollection(Supplier<C> collectionFactory)
产生一个将元素收集到任何集合中的收集器。可以传递一个诸如Treeset::new的构造器引用。

static Collector<CharSequence,?,String> joining()
static Collector<CharSequence,?,String> joining(CharSequence delimiter)
static Collector<CharSequence,?,String> joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)
产生一个连接字符串的收集器。分隔符会置于字符串之间,而第一个字符串之前可以有前缀,最后一个字符串之后可以有后缀。如果没有指定,那么它们都为空。

static <T> Collector<T,?,IntSummaryStatistics> summarizingint(ToIntFunction<?super T>mapper
产生能够生成(Int|Long|Double)SummaryStatistics对象的收集器,通过它可以获得将mapper应用于每个元素后所产生的结果的个数、总和、平均值、最大值和最小值。


如有谬误或不完善之处,恳请斧正。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐