该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2010-03-31
异常的思路挺好,不过一个是Stream一个是String对于substring功能的处理方式本来就不一样,没有可比性。
|
|
返回顶楼 | |
发表时间:2010-03-31
太感谢了 最近正在研究这类的问题
|
|
返回顶楼 | |
发表时间:2010-03-31
这不是split方法的问题,实际上,如果你是一个大字符串,用来拆成N个小串,那内存使用没有问题;但是如果你是接收N个大字符串,然后每个大串中仅需要保留一小部分,我觉得这应该是需要从源头上去解决,split的做法还是没有错
ps: 这种问题应该在压力测试的时候就暴露出来的,对网络传输、并发都是问题 |
|
返回顶楼 | |
发表时间:2010-03-31
iooyoo 写道 这不是split方法的问题,实际上,如果你是一个大字符串,用来拆成N个小串,那内存使用没有问题;但是如果你是接收N个大字符串,然后每个大串中仅需要保留一小部分,我觉得这应该是需要从源头上去解决,split的做法还是没有错
ps: 这种问题应该在压力测试的时候就暴露出来的,对网络传输、并发都是问题 很赞同你的说法 slite和subString的实现,我觉得很合理,只是我们使用时要充分了解。所以帖子的最后一个标题是“是否bug”。 确实没有做充分的、真实的压力测试,因此导致缓存的阈值设置过大,还没有开始淘汰,内存就超过预期了。 |
|
返回顶楼 | |
发表时间:2010-04-01
抛出异常的爱 写道 我说的不是stringTokenizer
是streamTokenizer 而且对于这么大的字串 一般用流来作才更合理一些。 string不适合这样的工作。 jarfield 写道 抛出异常的爱 写道 回去看了一下API
发现楼主用错API了 明明应当使用 streamTokenizer 非要用string这瘸子来搬砖头。。。。 StringTokenizer也是有问题的哦,最终还是调用了subString方法。 public String nextToken() { /* * If next position already computed in hasMoreElements() and * delimiters have changed between the computation and this invocation, * then use the computed value. */ currentPosition = (newPosition >= 0 && !delimsChanged) ? newPosition : skipDelimiters(currentPosition); /* Reset these anyway */ delimsChanged = false; newPosition = -1; if (currentPosition >= maxPosition) throw new NoSuchElementException(); int start = currentPosition; currentPosition = scanToken(currentPosition); return str.substring(start, currentPosition); } 注意最后一行对subString的调用。 我觉得,这个问题本质上不在于调用哪个API。而是在于String类在性能和安全上的权衡。如果要优化性能,split和subString那样的优化是很自然的,也无可厚非。只是,JavaDoc中应该明确说明。 我说的不是stringTokenizer import java.io.*; import java.util.*; class Counter { private int i = 1; int read() { return i; } void increment() { i++; } } public class SortedWordCount { private FileInputStream file; private StreamTokenizer st; private Hashtable counts = new Hashtable(); SortedWordCount(String filename) throws FileNotFoundException { try { file = new FileInputStream(filename); st = new StreamTokenizer(file); st.ordinaryChar('.'); st.ordinaryChar('-'); } catch(FileNotFoundException e) { System.out.println( "Could not open " + filename); throw e; } } void cleanup() { try { file.close(); } catch(IOException e) { System.out.println( "file.close() unsuccessful"); } } void countWords() { try { while(st.nextToken() != StreamTokenizer.TT_EOF) { String s; switch(st.ttype) { case StreamTokenizer.TT_EOL: s = new String("EOL"); break; case StreamTokenizer.TT_NUMBER: s = Double.toString(st.nval); break; case StreamTokenizer.TT_WORD: s = st.sval; // Already a String break; default: // single character in ttype s = String.valueOf((char)st.ttype); } if(counts.containsKey(s)) ((Counter)counts.get(s)).increment(); else counts.put(s, new Counter()); } } catch(IOException e) { System.out.println( "st.nextToken() unsuccessful"); } } Enumeration values() { return counts.elements(); } Enumeration keys() { return counts.keys(); } Counter getCounter(String s) { return (Counter)counts.get(s); } Enumeration sortedKeys() { Enumeration e = counts.keys(); StrSortVector sv = new StrSortVector(); while(e.hasMoreElements()) sv.addElement((String)e.nextElement()); // This call forces a sort: return sv.elements(); } public static void main(String[] args) { try { SortedWordCount wc = new SortedWordCount(args[0]); wc.countWords(); Enumeration keys = wc.sortedKeys(); while(keys.hasMoreElements()) { String key = (String)keys.nextElement(); System.out.println(key + wc.getCounter(key).read()); } wc.cleanup(); } catch(Exception e) { e.printStackTrace(); } } } 用来统计字数的代码倒子 惭愧啊,没有仔细看你写的“StreamTokenizer”,误以为是笔误。 刚仔细看了一下,在我的应用场景中,确实很适合用StreamTokenizer。你说的这个,确实是终极解决方案! 学习了,多谢多谢! |
|
返回顶楼 | |
发表时间:2010-04-01
优化要建立在性能测试工具的基础上,在性能测试工具测试出哪段代码确实有性能问题才去优化性能。
|
|
返回顶楼 | |
发表时间:2010-04-01
longhaisheng 写道 优化要建立在性能测试工具的基础上,在性能测试工具测试出哪段代码确实有性能问题才去优化性能。
赞同!好多关于性能的书上都建议:先测试,再有针对性的优化。不要过早优化、盲目优化。 |
|
返回顶楼 | |
发表时间:2010-04-02
最后修改:2010-04-02
楼主分析还是比较到位的,有研究精神,javaeye应该多些这样的帖子。
|
|
返回顶楼 | |
发表时间:2010-04-02
应该是你引用了字符串一直没有释放吧,这样的话,就算不用split,迟早也得内存溢出
|
|
返回顶楼 | |
发表时间:2010-04-03
mycybyb 写道 应该是你引用了字符串一直没有释放吧,这样的话,就算不用split,迟早也得内存溢出
我的本意是引用小String,数量达到阈值后自然淘汰。没想到引用的还是大String,没达到阈值,内存就超出预期了。 |
|
返回顶楼 | |