jrw*_*rws 7 java urlencode urldecode
我经常需要对大型集合或字符串数组进行url编码或解码.除了遍历它们并使用静态URLDecoder.decode(字符串,"UTF-8")之外,是否有任何库可以使这种类型的操作更高效?
一位同事坚持认为使用静态方法就地解码字符串不是线程安全的.那为什么会这样?
JDK URLDecoder没有有效实现.最值得注意的是,在内部它依赖于StringBuffer(在URLDecoder的情况下不必要地引入同步).Apache commons提供URLCodec,但据报道它在性能方面也存在类似的问题,但我还没有证实在最新版本中仍然存在这种情况.
Mark A. Ziesemer在一段时间前就URLDecoder的问题和性能撰写了一篇文章.他记录了一些错误报告,最后写了一个完整的替代品.因为这是SO,我会在这里引用一些关键的摘录,但你应该在这里阅读完整的源文章:http://blogger.ziesemer.com/2009/05/improving-url-coder-performance-java.html
精选报价:
Java在java.net.URLEncoder和java.net.URLDecoder中提供了此功能的默认实现.不幸的是,由于API的编写方式以及实现中的细节,它并不是最佳性能.在sun.com上提交了许多与URLEncoder相关的性能相关错误.
还有一个替代方案:来自Apache Commons Codec的org.apache.commons.codec.net.URLCodec.(Commons Codec还为Base64编码提供了一个有用的实现.)不幸的是,Commons的URLCodec遇到了一些与Java的URLEncoder/URLDecoder相同的问题.
...
JDK和Commons的建议:
构造任何"缓冲"类时,例如ByteArrayOutputStream,CharArrayWriter,StringBuilder或StringBuffer,估计并传入估计的容量.JDK的URLEncoder目前为其StringBuffer执行此操作,但也应为其CharArrayWriter实例执行此操作.Common的URLCodec应该为它的ByteArrayOutputStream实例执行此操作.如果类的默认缓冲区大小太小,它们可能必须通过复制到新的更大的缓冲区来调整大小 - 这不是一个"廉价"的操作.如果类的默认缓冲区大小太大,则可能会不必要地浪费内存.
这两种实现都依赖于Charsets,但只接受它们作为String名称.Charset为名称查找提供了一个简单的小缓存 - 仅存储最后使用的2个字符集.这不应该被依赖,并且两者都应该接受Charset实例以用于其他互操作性原因.
两种实现仅处理固定大小的输入和输出.JDK的URLEncoder仅适用于String实例.Commons的URLCodec也基于字符串,但也适用于byte []数组.这是一种设计级约束,实质上阻止了对较大或可变长度输入的有效处理.相反,应支持"流支持"接口,如CharSequence,Appendable和java.nio的ByteBuffer和CharBuffer的Buffer实现.
...
请注意,com.ziesemer.utils.urlCodec的速度是JDK URLEncoder的3倍,速度是JDK URLDecoder的1.5倍.(JDK的URLDecoder比URLEncoder的快,所以有没有很大的提升空间.)
我认为你的同事建议URLDecode不是线程安全的.其他答案在这里详细解释.
编辑[2012-07-03] - 每个评论由OP发布
不确定您是否在寻找更多创意?您是正确的,如果您打算在列表上作为原子集合进行操作,那么您必须同步对列表的所有访问,包括方法之外的引用.但是,如果您对返回的列表内容可能与原始列表有所不同,那么对于可能由其他线程修改的集合中的"批量"字符串进行操作的强力方法可能如下所示:
/**
* @param origList will be copied by this method so that origList can continue
* to be read/write by other threads.
* @return list containing decoded strings for each entry that was
in origList at time of copy.
*/
public List<String> decodeListOfStringSafely(List<String> origList)
throws UnsupportedEncodingException {
List<String> snapshotList = new ArrayList<String>(origList);
List<String> newList = new ArrayList<String>();
for (String urlStr : snapshotList) {
String decodedUrlStr = URLDecoder.decode(urlStr, "UTF8");
newList.add(decodedUrlStr);
}
return newList;
}
Run Code Online (Sandbox Code Playgroud)
如果这没有帮助,那么我仍然不确定你在追求什么,你会更好地创造一个新的,更简洁的问题.如果这就是你所要求的,那么要小心,因为这个例子脱离上下文并不是一个好主意,原因有很多.
| 归档时间: |
|
| 查看次数: |
8629 次 |
| 最近记录: |