前言:
toString() 方法 相信大家都用到过,一般用于以字符串的形式返回对象的相关数据。
最近项目中需要对一个 ArrayList<ArrayList<Integer>> datas 形式的集合处理。
处理要求把集合数据转换成字符串形式,格式为 :子集合 1 数据 +"#"+ 子集合 2 数据 +"#"+....+ 子集合 n 数据。
举例: 集合数据 :[[1,2,3],[2,3,5]] 要求转成为 "[1,2,3]#[2,3,5]" 形式的字符串
第一次是这样处理的:
- ArrayList> a =newArrayList<>(); // 打造这样一个数据的集合 [[1,2],[2,3]] 要求 生成字符串 [1,2]#[2,3]
- for(inti =0; i <2; i++) {
- ArrayList c = newArrayList<>();
- c.add(i+1);
- c.add(i+2);
- a.add(c);
- //打印单个子集合的字符串形式数据Log.i("myinfo",c.toString());
- }
- StringBuilder builder =new StringBuilder();
- builder.append(a.get(0).toString()+"#"+a.get(1).toString());
- //打印该集合的字符串形式数据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]
我们会发现我们想要的是 [1,2]#[2,3] 形式的字符串,但是结果是[1, 2]#[2, 3] ,在第二个值开始往后,前面都多了一个空格。
接下来我们查看 集合下的. toString() 方法的源码:
翻译一下官方解释:
1、返回这个 Collection 类 (Set 和 List 的父类) 的字符串表现形式
2、这个表现形式有一个规定的格式,被矩形括号 "[]" 包含
3、里面的子元素被 ","(逗号和空格)分割 (这是重点)
- /**
- * 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 =newStringBuilder(size() *16);
- buffer.append('[');
- Iteratorit = 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();
- }
分析这个 Collection 下的. toString() 方法源码,分为几个部分:
1、判断集合是不是空 (empty), 即集合内有没有数据。如果是空值(没有数据) 的话,直接返回字符串 "[]"
2、如果集合不是空值,说明有数据
①、迭代取下一个子元素 (Object next = it.next()),如果这个子元素是集合本身,添加 "(this Collection)" 到 StringBuffer 类的 buffer 对象中
②、如果这个子元素不是集合本身,添加到 buffer 对象中
③、如果这个子元素下面还有子元素,则添加 "," 到 buffer 对象中去,用于分割两个相邻子元素
3、返回 StringBuffer.toString() 字符串
由此可见,返回 [1, 2]#[2, 3] 是官方正确的返回形式,那么对于这个问题,其实在改不了源码的情况下 给得到的字符串后面使用. replaceAll("",""); 把字符串中的空格都去掉
注意:源码中有一段代码:
- if(next !=this) {
- buffer.append(next);
- } else {
- buffer.append("(this Collection)");
- }
这里可能有些同学看不懂,这里举个例子,还是上面的那个,我们在子集合里面 添加代码 c.add(c); 将集合本身添加到集合中去,看看打印结果
- ArrayList> a =newArrayList<>();
- for(inti =0; i <2; i++) {
- ArrayList c = newArrayList<>();
- c.add(i+1);
- c.add(i+2);
- c.add(c);
- //打印单个子集合的字符串形式数据Log.i("myinfo",c.toString());
- }看日志结果中红色部分,是不是看懂了,如果集合中的子元素是集合本身,就将"(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)]
至此,上面这个问题解决了,下面我们看下其他类下的. toString() 源码。
---------------------------------------------------------------------------------------------------------------
一、Object
- /**
- * 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() {
- returngetClass().getName() +'@'+ Integer.toHexString(hashCode());
- }
翻译一下官方解释:
1、返回一个对于这个 Object 简明的、可读的 的字符串
2、Object 类的子类被鼓励去重写这个方法来提供一个实现用于描述对象的类型和数据
3、默认的执行形式和下面这个例子一致
- getClass().getName() +'@'+ Integer.toHexString(hashCode())
综上:当你的一个类中没有重写. toString() 方法的时候就会执行根类 Object 的这个. toString() 方法。
返回形式:对象的类名 +@+ 哈希值的 16 进制
- getClass().getName()返回对象所属类的类名
- hashCode()返回该对象的哈希值
- Integer.toHexString(hashCode())将对象的哈希值用16进制表示
举例:
- 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
三个都是字符串的表现形式,但是有区别的
①、String.toString() , 直接返回本身
- /**
- * Returns this string.
- */
- @Override
- public String toString() {
- return this;
- }
②、StringBuilder
官方解释:以字符串的形式 返回这个 builder 对象的内容
- /**
- * 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() 实现
- /**
- * Returns the current String representation.
- *
- * @return a String containing the characters in this instance.
- */
- @Override
- public String toString() {
- if(count ==0) {
- return "";
- }
- returnStringFactory.newStringFromChars(0, count, value);
- }
③、StringBuffer
- @Override
- public synchronized String toString() {
- return super.toString();
- }
追溯到 super.toString()
- /**
- * Returns the current String representation.
- *
- * @return a String containing the characters in this instance.
- */@Override
- publicString toString() {
- if (count == 0) {
- return "";
- }
- return StringFactory.newStringFromChars(0, count, value);
- }
综上我们发现,StringBuffer 和 StringBuilder 最终都调用了父级 "AbstractStringBuilder" 中的 toString() 方法
但是他们本身的 toString() 却有所不同,我们由此可以总结
1、StringBuilder:线程非安全的
StringBuffer:线程安全的
2、StringBuilder 处理速度要比 StringBudiler 快的多
3、单线程大量数据操作,用 StringBuilder ,因为 StringBuilder 速度快 , 因为单线程所以不考虑安全性
多线程大量数据操作,用 StringBuffer , 因为 StringBuffer 安全
三、Map
先看源码:
可以看到返回的形式是 {key1=value1, key2=value2}
注意 1、当 Map 集合中没有数据的时候 返回 {}
2、每两个数据之前用 "," 分割,和 Collection 一致,一个逗号、一个空格
3、当键值是集合本身的时候,添加 (this Map)
- public String toString() {
- Iterator> i = entrySet().iterator();
- if(! i.hasNext())
- return "{}";
- StringBuilder sb =new StringBuilder();
- sb.append('{');
- for (;;) {
- Entry 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())
- returnsb.append('}').toString();
- sb.append(',').append(' ');
- }
- }
举例:
- Map map = new HashMap < >();
- map.put("keyA", "valueA");
- map.put("keyB", "valueB");
- map.put("keyC", "valueC");
- Log.i("myinfo", map.toString());打印结果:05 - 12 11 : 41 : 30.898 4490 - 4490 / com.maiji.magkarepatient I / myinfo: {
- keyA = valueA,
- keyB = valueB,
- keyC = valueC
- }
来源: http://www.cnblogs.com/xqxacm/p/6844861.html