清单4并没有消除出现I/O错误的可能性。这一点无法做到,因为这里的代码无力提供这样的功能。但是,可以将这个问题交给更合适的地方来处理。
避免问题
前面提到的方法有点复杂,所以我建议另一种方法:不使用内置的compare()函数或Collections.sort()。使用这样的函数也许比较方便,但是不适合当前情况。Comparable和Comparator是为确定的、可预测的比较操作而设计的。一旦I/O不再符合这种情况,很可能常用的算法和接口变得不适用。即使勉强可以使用,其效率也极其低下。
例如,假设不是按标准路径来比较文件,而是按内容来比较文件。对于所比较的两个文件,每个比较操作都需要读文件的内容—甚至可能是完整的内容。这样一来,高效的算法会想要尽量减少读的次数,并且可能会想缓存每次读的结果—或者,如果文件较大,则可能缓存每个文件的hashcode—而不是每次比较时重新读每个文件。同样,您会想到首先填充一个比较键列表,然后进行排序,而不是进行内联排序。可以想象定义一个单独的、并行的IOComparator接口,该接口抛出必要的异常,如清单5所示:
- 清单5.独立的IOComparator接口
- importjava.io.IOException;
- publicinterfaceIOComparator<T>{
- intcompare(To1,To2)throwsIOException;
-
- }
|
然后基于这个类定义一个单独的、相近实用程序树,由它对集合的临时副本进行必要的操作,从而允许抛出异常,同时又不会使数据结构处于可能受损害的、中间的状态。例如,清单6提供了一个基本的冒泡排序:
- 清单6.用冒泡算法对文件排序
- importjava.io.IOException;
- importjava.util.ArrayList;
- importjava.util.List;
-
- publicclassIOSorter{
-
- publicstatic<T>voidsort(List<T>list,IOComparator<?superT>comparator)
- throwsIOException{
- List<T>temp=newArrayList<T>(list.size());
- temp.addAll(list);
-
- bubblesort(temp,comparator);
-
- //copybacktooriginallistnowthatnoexceptionshavebeenthrown
- list.clear();
- list.addAll(temp);
- }
-
- //ofcourseyoucanreplacethiswithabetteralgorithmsuchasquicksort
- privatestatic<T>voidbubblesort(List<T>list,IOComparator<?superT>comparator)
- throwsIOException{
- for(inti=1;i<list.size();i++){
- for(intj=0;j<list.size()-i;j++){
- if(comparator.compare(list.get(j),list.get(j+1))>0){
- swap(list,j);
- }
- }
- }
- }
-
- privatestatic<T>voidswap(List<T>list,intj){
- Ttemp=list.get(j);
- list.set(j,list.get(j+1));
- list.set(j+1,temp);
- }
-
- }
|