16-案例实现
案例实现
根据如下步骤实现本案例:
1.首先,实现将在本例中使用的辅助类。创建一个名为 Person
的类,使之包含人的基础特征。这个类的源码参见6.2节。
2.由于要使用的方法依赖流中元素的顺序,因此必须要覆盖 Person
类的一些方法。首先,覆盖 compareTo()
方法来比较两个人。要创建一个静态的 Comparator
对象,需要用 Comparator
接口通过人的姓和名来比较两个 Person
对象,然后在 compareTo()
方法中使用这个比较器对象:
private static Comparator<Person> comparator=Comparator
.comparing(Person::getLastName)
.thenComparing(Person::getFirstName);
@Override
public int compareTo(Person otherPerson) {
return comparator.compare(this, otherPerson);
}
3.然后覆盖 equals()
方法来决定两个 Person
对象是否相等。与在 compareTo()
方法中一样,还是使用前面创建的 Comparator
静态对象:
@Override
public boolean equals(Object object) {
return this.compareTo((Person)object)==0;
}
4.最后覆盖 hashCode()
方法来为 Person
对象计算散列值。在Java里,由于两个相等的对象必须有相等的散列值,所以我们必须覆盖这个方法,并使用姓和名以及相应的方法来为 Person
对象生成散列值:
public int hashCode() {
String sequence=this.getLastName()+this.getFirstName();
return sequence.hashCode();
}
5.本案例也会使用6.2节中所用到的 PersonGenerator
和 DoubleGenerator
。
6.现在创建一个包含 main()
方法的 Main
类,并创建一个包含随机 Person
对象的列表:
public class Main {
public static void main(String[] args) {
List<Person> persons=PersonGenerator.generatePersonList(10);
7.然后用 forEach()
方法打印所有人的姓名。 forEach()
方法以表达式作为参数接收要应用到每个元素上的动作。在本案例中,我们用一个lambda表达式把信息写到控制台上:
persons.parallelStream().forEach(p -> {
System.out.printf("%s, %s\n", p.getLastName(),
p.getFirstName());
});
8.接下来学习如何按顺序应用一个动作到元素上。首先,用 DoubleGenerator
创建一个列表,它包含随机的 Double
型数字。然后创建一个并行流,并通过 sorted()
方法对元素进行排序,最后用 forEachOrdered()
方法以有序的方式把数字写到控制台上:
List<Double> doubles= DoubleGenerator.generateDoubleList(10, 100);
System.out.printf("Parallel forEachOrdered() with numbers\n");
doubles.parallelStream().sorted().forEachOrdered(n -> {
System.out.printf("%f\n",n);
});
9.现在,看看不使用 forEachOrdered()
方法对流中的元素进行排序会发生什么。重复上面的代码,改用 forEach()
方法:
System.out.printf("Parallel forEach() after sorted()
with numbers\n");
doubles.parallelStream().sorted().forEach(n -> {
System.out.printf("%f\n",n);
});
10.接着测试 forEachOrdered()
方法如何处理 Person
对象的流:
persons.parallelStream().sorted().forEachOrdered( p -> {
System.out.printf("%s, %s\n", p.getLastName(),
p.getFirstName());
});
11.最后测试 peek()
方法。该方法和 forEach()
方法类似,但它是一个中间操作。一般用作打印日志:
doubles
.parallelStream()
.peek(d -> System.out.printf("Step 1: Number: %f\n",d))
.peek(d -> System.out.printf("Step 2: Number: %f\n",d))
.forEach(d -> System.out.printf("Final Step: Number: %f\n",d));