本文分析CharSequence及其几个子类,如String、StringBuilder、StringBuffer、Editable。
1、通过反编译来比较String和StringBuilder性能
反编译:通过对可执行程序逆向分析,推导出他人软件的结构、思路、算法、原理,甚至源代码。
javac将Java源码编译成字节码(二进制文件),该class文件由JVM来执行。Java class可以运行在任何支持JVM的硬件平台和操作系统。
package com.qinuli.demo;
//package语句后面必须带分号
//函数名必须紧跟返回值类型
//在code目录执行javac -d .\bin verbose com\qinuli\demo\First.java
//在bin目录,生成类似等级结构。执行java -verbose com.qinuli.demo.First
public class First{
public static void main(String[] args){
System.out.println("Very good!");
}
}
javap用来查看Java编译器生成的字节码。可以查看Java代码在底层如何执行,判断是否高性能以及如何提高性能。
package com.qinuli.demo;
public class First{
public static void main(String[] args){
System.out.println("Very good!");
print();
printProtected();
}
private static void print(){
System.out.println("private method");
}
protected static void printProtected(){
System.out.println("protected method");
}
}
javap -c -public com.qinuli.demo.First >F://test.txt
-c除了方法声明,输出所有字节码指令。
-public只输出public的属性和方法,类似protected输出protected和public,private输出private、protected和public。
>将内容输出到指定路径文件。
若弹出“编码GBK的不可映射字符”,则可用用notepad.exe打开Java文件并另存为ANSI编码。
1)具体指令为
javac Hello.java
java Hello
javap -c -private Hello
编译指令含义:
ldc常量入栈,
astore_1出栈,
aload_1变量入栈
2)具体代码为
public class Hello{
static String s = "hehe";
public static void main(String[] args){
String str = "a"+"c";
String str2 = "b";
str = str+"Google"+"XX"+str2+"YY"+s;
//str += "Baidu";
}
String field = "grape";
private void initialize(){
String ss = "hh"+field;
ss += "A";
ss += "B";
ss += "C";
}
private void initialize2(){
StringBuilder sb = new StringBuilder();
sb.append("A");
sb.append("B");
sb.append("C");
}
}
3)反编译结果
4)String执行相加操作,需要先实例化一个StringBuilder,累加完后,再执行toString。因此性能不及直接用StringBuilder
2、StringBuffer使用及String、StringBuffer、StringBuilder的差别
StringBuffer stringBuffer = new StringBuffer("laugh loud");//实例化
stringBuffer.append("good");//追加
stringBuffer.reverse();//翻转
stringBuffer.delete(0, stringBuffer.length());//删除
System.out.println(stringBuffer.toString());
差别:1)StringBuffer和StringBuilder在字符串处理时不会生成新对象,内存使用优于String
2)StringBuffer是线程安全的,所以效率弱于StringBuilder
3、String常用方法
String str = "a.b.c.d.e.f";
//取代所有相应字符
Log.println(Log.INFO, TAG, str.replace('.', '_'));
//取代所有相应字符串
Log.println(Log.INFO, TAG, str.replace(".", "_"));
//target用regular expression
Log.println(Log.INFO, TAG, str.replaceAll("\\.[b-d]{1}", "_"));
//只取代首个
Log.println(Log.INFO, TAG, str.replaceFirst("\\.", "#"));
//两个字符串相应区域匹配
Log.println(Log.INFO, TAG, "regionMatches:"+str.regionMatches(true, 1, ".b.c", 0, 3));
//String继承3个接口(Serializable, Comparable<String>, CharSequence)
String str = null;
//全部大写或小写,将字符串转换为字符数组
str.toLowerCase();//String
str.toUpperCase();//String
str.toCharArray();//char[]
//方便给字符串排序,可忽略大小写
str.compareTo("");//String
str.compareToIgnoreCase("");//String
//判断字符串是否包含指定子串
str.contains("");//CharSequence, chars
str.substring(0,1);//String
str.subSequence(0, 1);//CharSequence
//判断俩字符串是否相等
str.equals("");//Object
str.equalsIgnoreCase("");//String
str.contentEquals("");//CharSequence, chars
输出结果:
2)示例讲解String的一些方法
int的二进制、八进制、十进制、十六进制输出;wrapper包含的几个常量;
System.arrayCopy, Arrays.toString, getBytes(), String.valueOf, matches等方法。
public class Client {
public static void main(String[] args) {
//补码表示
System.out.println("Integer.MIN_VALUE:"+Integer.toBinaryString(Integer.MIN_VALUE));
System.out.println("Integer.MAX_VALUE:"+Integer.toBinaryString(Integer.MAX_VALUE));
System.out.println("Integer.MIN_VALUE:"+Integer.toOctalString(Integer.MIN_VALUE));
System.out.println("Integer.MIN_VALUE:"+Integer.toHexString(Integer.MIN_VALUE));
System.out.println("Integer.MAX_VALUE:"+Integer.toString(Integer.MAX_VALUE, 8));
System.out.println("Integer.MAX_VALUE:"+Integer.toString(Integer.MAX_VALUE));//radix=10
// Float.SIZE;Float.MAX_VALUE;Float.MIN_VALUE;
// Double.SIZE;Double.MAX_VALUE;Double.MIN_VALUE
// Character.SIZE;Character.MAX_VALUE;Character.MIN_VALUE
// Boolean.TYPE;Boolean.TRUE;Boolean.FALSE
// Byte.MAX_VALUE;Byte.MIN_VALUE;Byte.SIZE
// Short.MAX_VALUE;Short.MIN_VALUE;Short.SIZE
// Long.MAX_VALUE;Long.MIN_VALUE;Long.SIZE
System.out.println("数组拷贝:");
int[] arr = new int[]{1,2,3,4,5};
int[] arr2 = new int[]{6,7,8,9,10};
System.arraycopy(arr, 0, arr2, 2, 2);
for(int j:arr2){
System.out.print(j+",");
}
//打印数组
System.out.println(Arrays.toString(new byte[]{-127,-128,127}));
byte[] multiple = new byte[]{'A','C',-128,-127,-64,127,64};
System.out.println(Integer.toBinaryString(multiple[0]));//0100,0001
StringBuilder sb = new StringBuilder();
for(byte single:multiple){
sb.append(single);//byte到int转换
}
System.out.println(Arrays.toString(sb.toString().getBytes()));
System.out.println(sb);//向上转型为Object
Client client = new Client();
System.out.println(String.valueOf(client));//相当于toString
String[] filenames = {"1.htm","1.1.htm","1.1.1.htm","1.2.htm","2.htm","2.1.htm",
"4.htm","10.htm","8.htm","8.html"};
for(int j=0;j<filenames.length;j++){
if(filenames[j].matches("[0-9]+\\.htm")){
System.out.println("篇:"+filenames[j]);
}else if(filenames[j].matches("[0-9]+\\.[0-9]+\\.htm")){
System.out.println("章:"+filenames[j]);
}else if(filenames[j].matches("[0-9]+\\.[0-9]+\\.[0-9]+\\.htm")){
System.out.println("节:"+filenames[j]);
}
}
for(int j=0;j<filenames.length;j++){
if(filenames[j].matches("1\\..+\\.htm")){
//有下级目录
break;
}
}
}
}
3)字符串拼接
String string = "You son of bitch!";
string = string.concat("-").concat("_");
char[] chars = new char[string.length()];
string.getChars(0, string.length(), chars, 0);//将字符串内容赋值到字符数组
String newString = new String(chars, 0, chars.length);//将字符数组转化为字符串
Log.d(TAG, "newString-"+newString);
4)字符串池
//利用对象池,提高效率,减少内存占用
//new并传参相当于创建了俩对象,参数存入字符串池
String string = new String("bastard");//查询字符串池,若字符串池不存在该字符串,先存入字符串池;存在,直接读取。
string.intern();//从字符串池读取
Log.d(TAG, "equal: "+(string==string.intern())+"-"+(string.equals(string.intern())));
HashMap<String, String> hashMap = new HashMap<>();//用HashMap实现字符串池
4、Editable接口
//EditText是TextView的直接子类,但TextView.getText()返回CharSequence,而EditText.getText()返回Editable
//Editable接口继承CharSequence, GetChars, Spannable, Appendable
//一个对象,链式
Editable editable = editText.getText();//Editable
editable.append('c');//char, CharSequence; Editable
editable.delete(0, 1);//; Editable
editable.insert(0, "c");//CharSequence; Editable
editText.setText("");//CharSequence
editable.clear();
//实现Spannable接口,如SpannableString
editable.clearSpans();
editable.removeSpan(null);
editable.setSpan(null, 0, 1, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
5、SpannableString
1) 用SpannableString设置局部字体颜色和粗斜体
private void setTextAppearance(String f, String s, String t){
SpannableString ss = new SpannableString(f+s+t);
ss.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 0, f.length(),
Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
ss.setSpan(new ForegroundColorSpan(Color.BLUE), f.length()+s.length(),
f.length()+s.length()+t.length(),
Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
TextView tv = (TextView) findViewById(R.id.txt);
tv.setText(ss);
}
2) 比较getString和getText的不同
//Context.getText
TextView textView = (TextView) findViewById(R.id.txt_getText);
textView.setText(getText(R.string.sometext));
//Context.getString
TextView textView2 = (TextView) findViewById(R.id.txt_getString);
textView2.setText(getString(R.string.sometext));
3) Html.fromHtml
TextView textView3 = (TextView) findViewById(R.id.txt_html);
textView3.setText(Html.fromHtml("<font color='red'>Very good!</font>"));
res/values/strings.xml文件内容
<string name="sometext">
<font color="blue">周杰伦</font>张靓颖<b>徐若瑄</b>
</string>