该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2010-03-30
最后修改:2010-03-30
应该回收没回收也叫泄露
楼主的系统中有一个阀值可以干掉全局的hashMAP 但是在这个阀值不是以字节数进行统计的。 所以。。。。算是泄露不是内存溢出 PS:刚刚的回贴被干掉了。。。。 楼下你不认为这样的回复也会被干掉么 |
|
返回顶楼 | |
发表时间:2010-03-30
有点类似于Buffer中的slice()方法。被分割出来的buffer和原来的buffer还共享同样的一个内部数组。
ByteBuffer bf = ByteBuffer.allocate(10) ; for(int i=0;i<bf.capacity() ;i++) { bf.put((byte)i) ; } bf.position(3) ; bf.limit(7) ; ByteBuffer bf2 = bf.slice() ; for(int i=0 ; i<bf2.capacity() ;i++) { byte b = bf2.get(i) ; b *= 11 ; bf2.put(i,b) ; } bf.position(0) ; bf.limit(bf.capacity()) ; while(bf.remaining() > 0) { System.out.println(bf.get()) ; } 输出结果: 0 1 2 33 44 55 66 7 8 9 |
|
返回顶楼 | |
发表时间:2010-03-30
skydream 写道 kimmking 写道 我也没看懂,hold的是引用,又不是char,怎么会有问题。
他并不是说所有split的小字符串都是从同一个大字符串下split出来的,不同的请求大字符串的来源不同,这样慢慢攒下来的。 还是你的表达能力 强啊。 |
|
返回顶楼 | |
发表时间:2010-03-30
查了一下javadoc,ByteBuffer明确了内容是同一个数组。String没有提示这点。
|
|
返回顶楼 | |
发表时间:2010-03-30
回去看了一下API
发现楼主用错API了 明明应当使用 streamTokenizer 非要用string这瘸子来搬砖头。。。。 |
|
返回顶楼 | |
发表时间:2010-03-30
抛出异常的爱 写道 回去看了一下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中应该明确说明。 |
|
返回顶楼 | |
发表时间:2010-03-30
lz最好在帖子上加上StringBuilder,StringBuffer就不会出这问题吧。要是很长的String,用这两个SB也是有优势的。StringBuilder,StringBuffer在j2me可惜了,要么没有这类,要么没substring这个方法。
|
|
返回顶楼 | |
发表时间:2010-03-30
鸟哥哥 写道 lz最好在帖子上加上StringBuilder,StringBuffer就不会出这问题吧。要是很长的String,用这两个SB也是有优势的。StringBuilder,StringBuffer在j2me可惜了,要么没有这类,要么没substring这个方法。
StringBuilder和StringBuffer的subString方法是确实安全的。 可问题是,得到的是一个大String对象。如果基于此对象构造一个StringBuilder,那么所有的字符都首先被拷贝一次。然后subString每次都会拷贝一部分字符。结果就是,所有的字符都被拷贝两次。 如果使用new String()的方式,所有字符只会被拷贝一次。 |
|
返回顶楼 | |
发表时间:2010-03-30
jarfield 写道 鸟哥哥 写道 lz最好在帖子上加上StringBuilder,StringBuffer就不会出这问题吧。要是很长的String,用这两个SB也是有优势的。StringBuilder,StringBuffer在j2me可惜了,要么没有这类,要么没substring这个方法。
StringBuilder和StringBuffer的subString方法是确实安全的。 可问题是,得到的是一个大String对象。如果基于此对象构造一个StringBuilder,那么所有的字符都首先被拷贝一次。然后subString每次都会拷贝一部分字符。结果就是,所有的字符都被拷贝两次。 如果使用new String()的方式,所有字符只会被拷贝一次。 帖子讨论的问题是内存溢出了。放SB里,String再=null,不省事,就不出溢出问题了嘛。 如果如此大的string,是否应该从char[]入手了?或者byte[]通过socket得到InputStream,一个个byte来读了? |
|
返回顶楼 | |
发表时间:2010-03-30
最后修改:2010-03-30
我说的不是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(); } } } 用来统计字数的代码倒子 |
|
返回顶楼 | |