当前位置:嗨网首页>书籍在线阅读

24-案例实现

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

案例实现

根据如下步骤实现本案例。

1.首先,实现将在本案例中使用的辅助类。先创建 Person 类来存储一个人的基本属性,然后创建 PersonGenerator 类来生成一个包含随机人员的 List 。这两个类的源代码参见6.5节。

2.创建一个名为 BasicPerson 的类。它包含一个 String 类型的 name 属性和一个 long 型的 age 属性。为这两个属性创建 get()set() 方法。由于这个类的代码非常简单,因此此处不再展示。

3.再创建一个辅助类 FileGenerator 。该类包含一个 generateFile() 方法—用于接收所模拟文件的行数,并返回一个包含 StringList 作为文件的内容。

public class FileGenerator {
  public static List<String> generateFile(int size) {
    List<String> file=new ArrayList<>();
    for (int i=0; i<size; i++) {
      file.add("Lorem ipsum dolor sit amet,
                consectetur adipiscing elit. Morbi lobortis
                cursus venenatis. Mauris tempus elit ut
                malesuada luctus. Interdum et malesuada fames
                ac ante ipsum primis in faucibus. Phasellus
                laoreet sapien eu pulvinar rhoncus. Integer vel
                ultricies leo. Donec vel sagittis nibh.
                Maecenas eu quam non est hendrerit pu");
    }
    return file;
  }
}

4.然后创建一个包含 main() 方法的 Main 类。在 main() 方法里,先用 PersonGenerator 创建一个 List —它应包含随机的 Person 对象:

public class Main {
  public static void main(String[] args) {
    // 创建包含随机人员的List
    List<Person> persons = PersonGenerator.generatePersonList(100);

5.使用 mapToDouble()Person 对象转换成包含双精度型数字的 DoubleStream 。先使用 parallelStream() 创建并行流,然后再使用 mapToDouble() 方法,传入一个接收 Person 对象的lambda表达式作为参数,并返回他的工资,其中工资是一个双精度型的数字。然后使用 distinct() 方法去除重复值,并使用 forEach() 方法把工资打印到控制台。另外,使用 count() 方法把不同元素的数量写到控制台:

DoubleStream ds = persons.parallelStream().mapToDouble
                                        (p -> p.getSalary());
ds.distinct().forEach(d -> {
  System.out.printf("Salary: %f\n", d);
});
ds = persons.parallelStream().mapToDouble(p -> p.getSalary());
long size = ds.distinct().count();
System.out.printf("Size: %d\n", size);

6.现在将流中的 Person 对象转换成 BasicPerson 对象。使用 parallelStream() 方法来创建流,并使用 map() 方法来转换对象。 map() 方法接收一个lambda表达式作为参数,并用这个表达式接收一个 Person 对象,然后创建一个新的 BasicPerson 对象并对其属性赋值。接着使用 forEach() 方法把 BasicPerson 对象的属性值打印到控制台:

List<BasicPerson> basicPersons = persons.parallelStream().map
                                                        (p -> {
  BasicPerson bp = new BasicPerson();
  bp.setName(p.getFirstName() + " " + p.getLastName());
  bp.setAge(getAge(p.getBirthDate()));
  return bp;
}).collect(Collectors.toList());
basicPersons.forEach(bp -> {
  System.out.printf("%s: %d\n", bp.getName(), bp.getAge());
});

7.最后,学习如何处理一个中间操作返回 Stream 的情况。在这种情况下,我们将处理一个包含流的 Stream ,不过可以使用 flatMap() 方法将所有这些 Stream 对象串联成唯一的一个 Stream 。使用 FileGenerator 生成一个包含100个元素的 List ,然后用 parallelStream() 方法创建一个并行流。我们将用 split() 方法把每行拆分成多个单词,并用 Stream 类的 of() 方法把结果数组转换成 Stream 。如果使用 map() 方法,则会得到一个包含流的 Stream ;而使用 flatMap() 方法,就能得到唯一的一个 Stream ,它包含整个 List 中所有单词的 String 对象。接着使用 filter() 去除长度等于0的单词,使用 sorted() 方法排序流,使用 groupingByConcurrent() 方法收集流得到一个 Map ,其 key 是这些单词, value 是每个单词出现在流中的次数:

List<String> file=FileGenerator.generateFile(100);
Map<String, Long> wordCount = file.parallelStream()
  .flatMap(line -> Stream.of(line.split("[ ,.]")))
  .filter(w -> w.length() > 0).sorted()
  .collect(Collectors.groupingByConcurrent(e -> e, Collectors
    .counting()));
wordCount.forEach((k, v) -> {
  System.out.printf("%s: %d\n", k, v);
});

8.最后还要实现前面代码中使用的 getAge() 方法。该方法接收一个人的出生日期并返回他的年龄:

private static long getAge(Date birthDate) {
  LocalDate start=birthDate.toInstant()
                .atZone(ZoneId.systemDefault()).toLocalDate();
  LocalDate now=LocalDate.now();
  long ret = ChronoUnit.YEARS.between(start, now);
  return ret;
}