当前位置:编程学习 > JAVA >>

Java实用技巧:当不能抛出checked异常时(2)

将问题一分为二

第一种办法是将问题一分为二。比较本身不会导致异常。比较的只是字符串而已。通过标准路径将文件转换成字符串才会导致异常。如果将可能抛出异常的操作与不会抛出异常的操作分开,那么问题就更容易处理了。也就是说,首先将所有文件对象转换为字符串,然后通过字符串比较器(甚至可以通过java.lang.String的自然排序)对字符串排序,最后使用排序后的字符串列表对原始的文件列表排序。这种方法不太直接,但是优点是在列表被改变之前就抛出IOException。如果出现异常,它只会出现在预先设计好的地方,不会造成损害,调用代码可以指定如何处理异常。清单4对此作了演示:

清单4.先读取,然后排序  importjava.io.File;  importjava.io.IOException;  importjava.util.ArrayList;  importjava.util.Collections;  importjava.util.HashMap;   publicclassFileComparator{   privatestaticArrayList<String>getCanonicalPaths(ArrayList<File>files)  throwsIOException{  ArrayList<String>paths=newArrayList<String>();  for(Filefile:files)paths.add(file.getCanonicalPath());  returnpaths;  }   publicstaticvoidmain(String[]args)throwsIOException{  ArrayList<File>files=newArrayList<File>();  for(Stringarg:args){  files.add(newFile(arg));  }   ArrayList<String>paths=getCanonicalPaths(files);   //tomaintaintheoriginalmapping  HashMap<String,File>map=newHashMap<String,File>();  inti=0;  for(Stringpath:paths){  map.put(path,files.get(i));  i++;  }   Collections.sort(paths);  files.clear();  for(Stringpath:paths){  files.add(map.get(path));  }  }   } 清单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);  }   } 这不是唯一的方法。为了清晰,清单6有意模仿已有的Collections.sort()方法;但是,也许更有效的方法是返回一个新的列表,而不是直接修改旧列表,以防在修改列表时抛出异常所带来的损害。


 

补充:软件开发 , Java ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,