前言:

toString()方法 相信大家都用到过,一般用于以字符串的形式返回对象的相关数据。

  

  最近项目中需要对一个ArrayList<ArrayList<Integer>> datas  形式的集合处理。

  处理要求把集合数据转换成字符串形式,格式为 :子集合1数据+"#"+子集合2数据+"#"+....+子集合n数据。

  举例: 集合数据 :[[1,2,3],[2,3,5]]  要求转成为 "[1,2,3]#[2,3,5]" 形式的字符串

  

  第一次是这样处理的:

        ArrayList<ArrayList<Object>> a = new ArrayList<>();    // 打造这样一个数据的集合 [[1,2],[2,3]] 要求 生成字符串 [1,2]#[2,3]
for (int i = ; i < ; i++) {
ArrayList<Object> c = new ArrayList<>();
c.add(i+);
c.add(i+);
a.add(c);
//打印单个子集合的字符串形式数据
Log.i("myinfo",c.toString());
}
StringBuilder builder = new StringBuilder();
builder.append(a.get().toString()+"#"+a.get().toString());
//打印该集合的字符串形式数据
Log.i("myinfo",builder.toString());

  

  然后看该处理下的Log日志:

- ::18.485 -/com.xxx.aaa I/myinfo: [, ]
- ::18.485 -/com.xxx.aaa I/myinfo: [, ]
- ::18.495 -/com.xxx.aaa I/myinfo: [, ]#[, ]

  我们会发现我们想要的是[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 = new StringBuilder(size() * );
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();
}

   

  分析这个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<ArrayList<Object>> a = new ArrayList<>();
for (int i = ; i < ; i++) {
ArrayList<Object> c = new ArrayList<>();
c.add(i+);
c.add(i+);
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() {
return getClass().getName() + '@' + Integer.toHexString(hashCode());
}

  翻译一下官方解释:

  1、返回一个对于这个Object 简明的、可读的 的字符串

  2、Object类的子类被鼓励去重写这个方法来提供一个实现用于描述对象的类型和数据

  3、默认的执行形式和下面这个例子一致

getClass().getName() + '@' + Integer.toHexString(hashCode())</pre>

  综上:当你的一个类中没有重写.toString()方法的时候就会执行根类Object的这个.toString()方法。

     返回形式:对象的类名+@+哈希值的16进制

getClass().getName()返回对象所属类的类名
hashCode()返回该对象的哈希值
Integer.toHexString(hashCode())将对象的哈希值用16进制表示

 举例:

Object d = new Object();
Log.i("myinfo",d.toString()); - ::00.758 -/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 == ) {
return "";
}
return StringFactory.newStringFromChars(, 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
public String 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<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(' ');
}
}

  举例:

       Map<String,String> 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}

  

源码浅谈(一):java中的 toString()方法的更多相关文章

  1. Java中的toString()方法

    Java中的toString()方法 目录 Java中的toString()方法 1.    对象的toString方法 2.    基本类型的toString方法 3.    数组的toString ...

  2. Java中的 toString 方法

    1. Object 类中定义有 public String toString() 方法,其返回值是 String 类型,描述当前对象的有关信息: 2. 在进行 String 与其它类型数据的连接操作时 ...

  3. 源码浅谈(二):java中的 Integer.parseInt(String str)方法

    这个方法是将字符串转换为整型 一.parseInt方法 ,可以看到默认又调用了parseInt(s,10) ,  第二个参数为基数,默认10 ,当然也可以自己设置  public static int ...

  4. 【Android测试】【第七节】Monkey——源码浅谈

    ◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/4713466.html 前言 根据上一篇我们学会了Monke ...

  5. 【Android测试】【第三节】ADB——源码浅谈

    ◆版权声明:本文出自carter_dream的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/4651724.html 前言 由于本人精力 ...

  6. 结合源码浅谈Spring容器与其子容器Spring MVC 冲突问题

    容器是整个Spring 框架的核心思想,用来管理Bean的整个生命周期. 一个项目中引入Spring和SpringMVC这两个框架,Spring是父容器,SpringMVC是其子容器,子容器可以看见父 ...

  7. 浅谈对java中传参问题的理解

    之前用的c/c++比较多,在c/c++中对于传参类型,无外乎就是传值.传引用.传指针这几种.但在java中,由于没有指针类型,其传参的方式也发生了相应的变化.在网上找了找,按我之前的理解,java中传 ...

  8. 从源码和doc揭秘——Java中的Char究竟几个字节,Java与Unicode的关系

    #编码与字符编码 (懂编码的建议直接跳过) 在计算机世界中,任何事物都是用二进制图片数字表示的,图片可以编码为JPG,PNG格式的字节流,音频,视频有MP3,MP4格式的字节流.这些JPG,MP3等都 ...

  9. glibc memcpy() 源码浅谈

    其实我本来只是想搞懂为什么memcpy()函数的参数类型是void *的: 我以为会在memcpy()源码中能找到答案,其实并没有,void *只是在传递参数的时候起了作用,可以让memcpy()接受 ...

随机推荐

  1. 知问前端——html+jq+jq_ui+ajax

    **************************************************************************************************** ...

  2. Vue.js 插件开发详解

    前言 随着 Vue.js 越来越火,Vue.js 的相关插件也在不断的被贡献出来,数不胜数.比如官方推荐的 vue-router.vuex 等,都是非常优秀的插件.但是我们更多的人还只停留在使用的阶段 ...

  3. Web前端面试指导(十四):如何居中一个元素(正常、绝对定位、浮动元素)?

    题目点评 这道题目的提问比较多,连续问了三个问题,正常元素.绝对定位元素.互动元素如何居中,而且居中没有说清楚是垂直居中还是水平居中,要回答清楚这个问题,必须得有深厚的功底,而且要分类的来回答,条理要 ...

  4. 【SoDiaoEditor更新啦】--谨以献给那些还在医疗行业奋斗的小伙伴们

    先放github地址:https://github.com/tlzzu/SoDiaoEditor.v2 首先,这不是愚人节的玩笑,,, 本想着三月底发布来着,结果昨天又在兼容性上调出几个bug,然后拖 ...

  5. 每天学点Java小知识【1】

    一 Java标识符和关键字 1.标识符 作用:用来标识类名.变量名.方法名.类型名.数组名.文件名的有效字符序列. 组成规则:由字母.下划线.美元符号和数字组成,且第一个字符不能是数字字符.注意:标识 ...

  6. Tcl与Design Compiler (十二)——综合后处理

    本文如果有错,欢迎留言更正:此外,转载请标明出处 http://www.cnblogs.com/IClearner/  ,作者:IC_learner 概述 前面也讲了一些综合后的需要进行的一些工作,这 ...

  7. python 语句:条件、循环、break、continue...

    1. 条件语句 执行条件:判断条件"成立时(非零),则执行后面的语句,而执行内容可以多行,以缩进来区分表示同一范围. [Python程序语言指定任何非0和非空(null)值为true,0 或 ...

  8. 02 Learning to Answer Yes/No

    Perceptron Learning Algorithm 感知器算法, 本质是二元线性分类算法,即用一条线/一个面/一个超平面将1,2维/3维/4维及以上数据集根据标签的不同一分为二. 算法确定后, ...

  9. linux里的那么点东西(持续更新)

    作为一个程序猿的确是应该上的了windows,下的了linux的.但是由于没有对linux产生一些刚性的需求,所以使用的次数还是略少,对一些基本的concept和command还是有一些生疏.借着最近 ...

  10. js 形参和实参---2017-04-11

    一.定义 1.实参(argument):     全称为"实际参数"是在调用时传递给函数的参数. 实参可以是常量.变量.表达式.函数等, 无论实参是何种类型的量,在进行函数调用时, ...