通过使用过滤迭代器类,你可以避免这种低效率的处理方式:遍历一个迭代器中的对象,用满足过滤条件的对象来创建另外一个包含原迭代器对象集子集的新迭代器。例如,如果你有一个内置对象和空值(NULL)的迭代器,并且你只想要非空值的对象,使用过滤迭代器类能使花费较短的处理时间和较少的内存进行有效的处理。
迭代器对象提供了一个很好的表示对象顺序的机制,因为它们既不象数组那样储存对象的值,也不象链表那样储存对象的引用。相反,它只是简单的提供能访问分离的对象源所提供的对象的一些方法。这样就可以因为避免储存重复的对象而带来的内存消耗。因为如果函数体不用完全知道迭代器对象,在迭代器对象中包含的拷贝对象就不需要被创建,所以将迭代器对象作为函数参数进行传递也比传递克隆的列表对象更快些。
Listing A 这个列表包含过滤迭代器类的源代码。这个过滤迭代器带有在源迭代器中发现的对象,通过一个在对象实例化时提供的简单测试来过滤这些对象。通过过滤迭代器自身的迭代器接口方法来获得被测试的对象,让我们仔细的看看Listing A中的代码,研究一下这个过滤迭代器类到底是如何工作的。
由于过滤迭代器类的定义中实现了接口java.util.Iterator,所以它必须实现该接口定义中的所有方法。由此可见,过滤迭代器类应该有remove、hasNext、和next方法。因为方法remove在过滤迭代器类中没有起什麽具体作用,所以它在类中并没有具体的实现代码,当它被调用时只是简单的返回异常UnsupportedOperationException。
方法hasNext用来处理对象过滤,在这个方法里面有一个while循环依次处理源迭代器提供的对象,直到在源过滤器中发现一个能通过测试的对象或完成对源迭代器中所有对象的遍历。在这个过程中如果有通过测试的对象,那么该对象的一个引用就会被存储在类过滤迭代器的属性next中并且返回一个真值(true),如果遍历完源迭代器并且没有发现满足测试条件的对象,一个null值被存储到类过滤迭代器的属性next中并且返回一个假值(false)。
方法next调用方法hasNext来判断是否有满足测试条件的对象。如果没有发现满足测试条件的对象,方法next根据java.util.Iterator接口的需要扔出一个NoSuchElementException的异常。如果方法hasNext返回真值(true),表明可以找到满足条件的对象,这时过滤迭代器类的属性next被赋值给一个临时变量(retval),然后将过滤迭代器类的属性next置成null值,最后返回那个临时变量的值。
请注意,正如Java所提供的那些集合类一样,在这个类中也没有实现同步。通常让创建和使用集合类的代码来实现同步可以使开发者更灵活的设计代码。因此,如果你想通过多个线程来同时访问单个过滤迭代器类,你必须为过滤迭代器类实现同步,在java中简单的方法是只需在需要同步的方法前加上同步标志即可。
在Listing A的代码中,方法hasNext通过调用一个命名为accept的函数来实现对象过滤,但是你可以发现该函数是抽象的,它接受一个对象类型的参数并返回一个布尔值,在函数体中并没有具体过滤规则的实现,其实上使用这个过滤迭代器类的类必须重载这个函数来提供具体的过滤逻辑,这样使得过滤迭代器类的使用更灵活。从accept在方法hasNext中的用法可知,如果被测试的对象满足条件,accept返回真值(true),否则丢弃该对象,让hasNext继续遍历源迭代器中的对象。