接上一小节,本小节将着手使用 "流" 这一概念进行 "迭代" 操作。
首先何为 "迭代"。其意为对某一对象进行某种操作,并把结果作为下一次操作的输入,如此往复进行,直至得到或逼近预期结果。
现在我们用代码来具体表示对某一集合进行迭代操作,我们希望定义一个 Contact 类来表示联系人,并将 ContactList 中所有 String 类型的联系人姓名全部包装进 Contact 类中:
- List contacts = new ArrayList<>();
- contactList.forEach(new Consumer() {
- @Override
- public void accept(String s) {
- Contact contact = new Contact();
- contact.setName(s);
- contacts.add(contact);
- }
- });
接下来我们希望筛选出所有还能打通的联系人,将其放入一个有效联系人集合:
- List validContacts = new ArrayList<>();
- contacts.forEach(new Consumer() {
- @Override
- public void accept(Contact c) {
- if (c.call())
- validContacts.add(c);
- }
- });
- System.out.println(validContacts.size());
可以看出,第一次操作我们将 String 类型的数据转换为 Contact,第二次则对每一个 Contact 调用
方法,筛选出返回结果为
- call()
的联系人并将其收集进另一个集合,最后我们统计出还能打通的联系人数目。 在此过程中,操作行为完全封闭在各个集合内部,无需引入任何外部变量。 从处理开始、进行到结束,对象在操作间如同一个有序序列在移动,这就是流的特征,即 "移动中的数据"。 真正的流与集合大相径庭,其只表示一种 "可选的有序值序列",而 "无需为这些值提供任何存储",这就是为何
- true
在 Java8-API 中被定义为接口而非一种类。
- Stream
- public interface Stream extends BaseStream> {}
为对象的流,而
- Stream<T>
、
- DoubleStream
以及
- LongStream
则为 double、long 以及 int 这三种基本类型的流。 现在我们再将第一次从 String 到 Contact 的映射用流的方式来重写:
- IntStream
- Stream contactStream = contactList.stream().map(s -> new Contact().setName(s));
从源中取得管道,表示流的开始。
- stream()
接收管道中的流并对其进行某种变换,在本例中,我们将管道中的 String 映射成为 Contact 类,自此,String 管道成为 Contact 管道。 我们可以将上一段代码拆分为:
- map()
- Stream stringStream = contactList.stream();
- Stream contactStream1 = stringStream.map(s -> new Contact().setName(s));
在基本搞清了流操作之后,我们现在一气呵成,直接使用流得到最终结果:
- long validContactCounter =
- contactList.stream()
- .map(s -> new Contact().setName(s))
- .filter(c -> c.call())
- .count();
可以看出,我们对流能够进行丰富的操作,过滤、计数、查找等等,在此不表。
使用流的方式处理数据能够精简代码,同时突出了所要进行的操作,当然乍看起来有些难懂。
既然牺牲了些许可读性,但是作为交换条件,我们在这种顺序执行的流操作中,获得了两倍于相应的循环版本的性能。
同样,并行执行流操作对于大型数据集将产生非凡的效果。
本小节相关代码:
(Contact.java)
- import java.util.Random;
- public class Contact {
- private String name;
- private long number;
- private Random random;
- public Contact() {
- random = new Random();
- }
- public String getName() {
- return name;
- }
- public Contact setName(String name) {
- this.name = name;
- return this;
- }
- public long getNumber() {
- return number;
- }
- public Contact setNumber(long number) {
- this.number = number;
- return this;
- }
- public boolean call() {
- return random.nextBoolean();
- }
- }
(运行用)
- List contacts = new ArrayList<>();
- contactList.forEach(new Consumer() {
- @Override
- public void accept(String s) {
- Contact contact = new Contact();
- contact.setName(s);
- contacts.add(contact);
- }
- });
- List validContacts = new ArrayList<>();
- contacts.forEach(new Consumer() {
- @Override
- public void accept(Contact contact) {
- if (contact.call())
- validContacts.add(contact);
- }
- });
- System.out.println(validContacts.size());
- //--- Stream is coming ---//
- Stream contactStream = contactList.stream().map(s -> new Contact().setName(s));
- //--- Break this code ---//
- Stream stringStream = contactList.stream();
- Stream contactStream1 = stringStream.map(s -> new Contact().setName(s));
- //--- All in one ---//
- long validContactCounter =
- contactList.stream()
- .map(s -> new Contact().setName(s))
- .filter(c -> c.call())
- .count();
- System.out.println(validContactCounter);
以及运行结果:
- 3
- 3
来源: