前言:
toString()方法 相信大家都用到過,一般用于以字符串的形式返回對(duì)象的相關(guān)數(shù)據(jù)。
最近項(xiàng)目中需要對(duì)一個(gè)ArrayList<ArrayList<Integer>> datas 形式的集合處理。
處理要求把集合數(shù)據(jù)轉(zhuǎn)換成字符串形式,格式為 :子集合1數(shù)據(jù)+"#"+子集合2數(shù)據(jù)+"#"+....+子集合n數(shù)據(jù)。
舉例: 集合數(shù)據(jù) :[[1,2,3],[2,3,5]] 要求轉(zhuǎn)成為 "[1,2,3]#[2,3,5]" 形式的字符串
第一次是這樣處理的:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
ArrayList<ArrayList<Object>> a = new ArrayList<>(); // 打造這樣一個(gè)數(shù)據(jù)的集合 [[1,2],[2,3]] 要求 生成字符串 [1,2]#[2,3] for ( int i = 0 ; i < 2 ; i++) { ArrayList<Object> c = new ArrayList<>(); c.add(i+ 1 ); c.add(i+ 2 ); a.add(c); //打印單個(gè)子集合的字符串形式數(shù)據(jù) Log.i( "myinfo" ,c.toString()); } StringBuilder builder = new StringBuilder(); builder.append(a.get( 0 ).toString()+ "#" +a.get( 1 ).toString()); //打印該集合的字符串形式數(shù)據(jù) Log.i( "myinfo" ,builder.toString()); |
然后看該處理下的Log日志:
05-12 10:29:18.485 9565-9565/com.xxx.aaa I/myinfo: [1, 2]
05-12 10:29:18.485 9565-9565/com.xxx.aaa I/myinfo: [2, 3]
05-12 10:29:18.495 9565-9565/com.xxx.aaa I/myinfo: [1, 2]#[2, 3]
我們會(huì)發(fā)現(xiàn)我們想要的是[1,2]#[2,3]形式的字符串,但是結(jié)果是[1, 2]#[2, 3] ,在第二個(gè)值開始往后,前面都多了一個(gè)空格。
接下來(lái)我們查看 集合下的.toString()方法的源碼:
翻譯一下官方解釋:
1、返回這個(gè)Collection類(Set和List的父類) 的字符串表現(xiàn)形式
2、這個(gè)表現(xiàn)形式有一個(gè)規(guī)定的格式,被矩形括號(hào)"[]"包含
3、里面的子元素被“, ”(逗號(hào)和空格)分割 (這是重點(diǎn))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
/** * Returns the string representation of this {@code Collection}. The presentation * has a specific format. It is enclosed by square brackets ("[]"). Elements * are separated by ', ' (comma and space). * * @return the string representation of this {@code Collection}. */ @Override public String toString() { if (isEmpty()) { return "[]" ; } StringBuilder buffer = new StringBuilder(size() * 16 ); buffer.append( '[' ); Iterator<?> it = iterator(); while (it.hasNext()) { Object next = it.next(); if (next != this ) { buffer.append(next); } else { buffer.append( "(this Collection)" ); } if (it.hasNext()) { buffer.append( ", " ); } } buffer.append( ']' ); return buffer.toString(); } |
分析這個(gè)Collection下的.toString()方法源碼,分為幾個(gè)部分:
1、判斷集合是不是空(empty),即集合內(nèi)有沒有數(shù)據(jù)。如果是空值(沒有數(shù)據(jù))的話,直接返回字符串 "[]"
2、如果集合不是空值,說明有數(shù)據(jù)
①、迭代取下一個(gè)子元素(Object next = it.next()),如果這個(gè)子元素是集合本身,添加"(this Collection)"到StringBuffer類的buffer對(duì)象中
②、如果這個(gè)子元素不是集合本身,添加到buffer對(duì)象中
③、如果這個(gè)子元素下面還有子元素,則添加", "到buffer對(duì)象中去,用于分割兩個(gè)相鄰子元素
3、返回StringBuffer.toString()字符串
由此可見,返回[1, 2]#[2, 3]是官方正確的返回形式,那么對(duì)于這個(gè)問題,其實(shí)在改不了源碼的情況下 給得到的字符串后面使用.replaceAll(" ",""); 把字符串中的空格都去掉
注意:源碼中有一段代碼:
1
2
3
4
5
|
if (next != this ) { buffer.append(next); } else { buffer.append( "(this Collection)" ); } |
這里可能有些同學(xué)看不懂,這里舉個(gè)例子,還是上面的那個(gè),我們?cè)谧蛹侠锩?添加代碼 c.add(c); 將集合本身添加到集合中去,看看打印結(jié)果
1
2
3
4
5
6
7
8
9
|
ArrayList<ArrayList<Object>> a = new ArrayList<>(); for ( int i = 0 ; i < 2 ; i++) { ArrayList<Object> c = new ArrayList<>(); c.add(i+ 1 ); c.add(i+ 2 ); c.add(c); //打印單個(gè)子集合的字符串形式數(shù)據(jù) Log.i( "myinfo" ,c.toString()); } |
看日志結(jié)果中紅色部分,是不是看懂了,如果集合中的子元素是集合本身,就將"(this Collection)" 添加到返回集合中
05-12 10:58:00.615 8424-8424/com.maiji.magkarepatient I/myinfo: [1, 2, (this Collection)]
05-12 10:58:00.615 8424-8424/com.maiji.magkarepatient I/myinfo: [2, 3, (this Collection)]
至此,上面這個(gè)問題解決了,下面我們看下其他類下的.toString()源碼。
一、Object
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/** * Returns a string containing a concise, human-readable description of this * object. Subclasses are encouraged to override this method and provide an * implementation that takes into account the object's type and data. The * default implementation is equivalent to the following expression: * <pre> * getClass().getName() + '@' + Integer.toHexString(hashCode())</pre> * <p>See <a href="{@docRoot}reference/java/lang/Object.html#writing_toString">Writing a useful * {@code toString} method</a> * if you intend implementing your own {@code toString} method. * * @return a printable representation of this object. */ public String toString() { return getClass().getName() + '@' + Integer.toHexString(hashCode()); } |
翻譯一下官方解釋:
1、返回一個(gè)對(duì)于這個(gè)Object 簡(jiǎn)明的、可讀的 的字符串
2、Object類的子類被鼓勵(lì)去重寫這個(gè)方法來(lái)提供一個(gè)實(shí)現(xiàn)用于描述對(duì)象的類型和數(shù)據(jù)
3、默認(rèn)的執(zhí)行形式和下面這個(gè)例子一致
1
|
getClass().getName() + '@' + Integer.toHexString(hashCode())</pre> |
綜上:當(dāng)你的一個(gè)類中沒有重寫.toString()方法的時(shí)候就會(huì)執(zhí)行根類Object的這個(gè).toString()方法。
返回形式:對(duì)象的類名+@+哈希值的16進(jìn)制
1
2
3
|
getClass().getName()返回對(duì)象所屬類的類名 hashCode()返回該對(duì)象的哈希值 Integer.toHexString(hashCode())將對(duì)象的哈希值用 16 進(jìn)制表示 |
舉例:
1
2
|
Object d = new Object(); Log.i( "myinfo" ,d.toString()); |
05-12 11:23:00.758 17406-17406/com.maiji.magkarepatient I/myinfo: java.lang.Object@e23e786
二、String,StringBuilder,StringBuffer
三個(gè)都是字符串的表現(xiàn)形式,但是有區(qū)別的
①、String.toString() , 直接返回本身
1
2
3
4
5
6
7
|
/** * Returns this string. */ @Override public String toString() { return this ; } |
②、StringBuilder
官方解釋:以字符串的形式 返回這個(gè)builder對(duì)象的內(nèi)容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/** * Returns the contents of this builder. * * @return the string representation of the data in this builder. */ @Override public String toString() { /* Note: This method is required to workaround a compiler bug * in the RI javac (at least in 1.5.0_06) that will generate a * reference to the non-public AbstractStringBuilder if we don't * override it here. */ return super .toString(); } |
追溯到super.toString()實(shí)現(xiàn)
1
2
3
4
5
6
7
8
9
10
11
12
|
/** * Returns the current String representation. * * @return a String containing the characters in this instance. */ @Override public String toString() { if (count == 0 ) { return "" ; } return StringFactory.newStringFromChars( 0 , count, value); } |
③、StringBuffer
1
2
3
4
|
@Override public synchronized String toString() { return super .toString(); } |
追溯到super.toString()
1
2
3
4
5
6
7
8
9
10
11
12
|
/** * Returns the current String representation. * * @return a String containing the characters in this instance. */ @Override public String toString() { if (count == 0 ) { return "" ; } return StringFactory.newStringFromChars( 0 , count, value); } |
綜上我們發(fā)現(xiàn),StringBuffer和StringBuilder最終都調(diào)用了父級(jí) “AbstractStringBuilder” 中的toString()方法
但是他們本身的toString()卻有所不同,我們由此可以總結(jié)
1、StringBuilder:線程非安全的
StringBuffer:線程安全的
2、StringBuilder 處理速度要比 StringBudiler 快的多
3、單線程大量數(shù)據(jù)操作,用StringBuilder ,因?yàn)?StringBuilder速度快 , 因?yàn)閱尉€程所以不考慮安全性
多線程大量數(shù)據(jù)操作,用StringBuffer , 因?yàn)镾tringBuffer安全
三、Map
先看源碼:
可以看到返回的形式是{key1=value1, key2=value2}
注意 1、當(dāng)Map集合中沒有數(shù)據(jù)的時(shí)候 返回{}
2、每?jī)蓚€(gè)數(shù)據(jù)之前用", "分割,和Collection一致,一個(gè)逗號(hào)、一個(gè)空格
3、當(dāng)鍵值是集合本身的時(shí)候,添加 (this Map)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public String toString() { Iterator<Entry<K,V>> i = entrySet().iterator(); if (! i.hasNext()) return "{}" ; StringBuilder sb = new StringBuilder(); sb.append( '{' ); for (;;) { Entry<K,V> e = i.next(); K key = e.getKey(); V value = e.getValue(); sb.append(key == this ? "(this Map)" : key); sb.append( '=' ); sb.append(value == this ? "(this Map)" : value); if (! i.hasNext()) return sb.append( '}' ).toString(); sb.append( ',' ).append( ' ' ); } } |
舉例:
1
2
3
4
5
|
Map<String,String> map = new HashMap<>(); map.put( "keyA" , "valueA" ); map.put( "keyB" , "valueB" ); map.put( "keyC" , "valueC" ); Log.i( "myinfo" ,map.toString()); |
打印結(jié)果:
1
|
05 - 12 11 : 41 : 30.898 4490 - 4490 /com.maiji.magkarepatient I/myinfo: {keyA=valueA, keyB=valueB, keyC=valueC} |
以上所述是小編給大家介紹的java中的 toString()方法實(shí)例代碼,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)服務(wù)器之家網(wǎng)站的支持!
原文鏈接:http://www.cnblogs.com/xqxacm/p/6844861.html