java学习笔记--String字符串,StringBuffer和StringBuilder总结

String
先来介绍一下字符串的存储
字符串相加是通过StringBuffer类的append()和toString()实现的, 而toString()返回的字符串是通过构造函数创建的

强调: 两个字符串常量相加, 在编译的时候之间改为一个字符串常量.
而字符串引用相加则是调用StringBuffer类的append()和toString() 这个时候就会在堆中创建一个新的对象。

比较对象的时候==和euqals比较的都是对象的内存地址
对于其他对象类来说 hascode默认代表是内存地址 equals判断的是地址

但是String类重写了equals和hascode 只要值一样 那么hascode就一样 比较的是两个字符串对象内容是否相一致
所以一般都是equals来比较字符串是否相等

注意:了解一下String继承了Comparable重写了compareTo(compareTo)主要是放在集合里判断大小用

编程习惯 常量调用equals方法 比如: “sdf”.equals(str);因为 如果 调用者是空的话会抛异常

String name1="hello"; 
String name2=new String(“hello”);

创建字符串的时候 jvm会检查字符串常量池是否存在“hello”的字符串
如果存在就不会在里面创建字符串对象了
如果是第一个那么就会返回的是字符串常量池的地址
如果是第二个 都会拷贝一份字符串常量池的对象内容到堆内存中
字符串常量池只能有一个对象
而堆内存中可以有多个对象而且地址不一样
字符串常量池在方法区中
name1等引用在栈内存中
对象内存中new的话
例子:

String str1 = "hello";
    String str2 = "hello";
    String str3 = new String("hello");
    String str4 = new String("hello");
    System.out.println("str1==str2?"+(str1==str2));  // true  
    System.out.println("str2==str3?"+(str2==str3));  //false
    System.out.println("str3==str4?"+(str3==str4));  // false
    System.out.println("str3.equals(str2)?"+(str3.equals(str4))); //true

字符串判断是否内容相等

   public static void test(String str){
            if("中国".equals(str))
            {
                System.out.println("回答正确");
            }else{
                System.out.println("回答错误");
            }
        }

字符串的构造

public static void main(String[] args) {

    String name=new String();  //空内容 
    byte[] buf= {97,98,99}; 
    name=new String(buf,0,2);   //0是索引 2是个数  输出ab
    char[] arr= {'我','爱','你'};
    name=new String(arr,0,2);      //同理byte 输出我爱
    int[] buf2= {97,98,99};
    name=new String(buf,0,2);   //同类byte 输出ab
    name=new String("wocainima00"); //输出wocainima00 
    name="xxx";           //输出xxx     
    System.out.print(name);    
}

字符串获取长度,位置或者获取字串:
int length() 获取字符串的长度
char charAt(int index) 获取特定位置的字符 (角标越界)
int indexOf(String str) 查找子串第一次出现的索引值,如果子串没有出现 在字符串中,那么则返回-1表示。
int lastIndexOf(String str) 查找子串最后一次出现的索引值 , 如果子串没有出现 在字符串中,那么则返回-1表示

字符串的判断:
字节数组与字符数组、字符串他们三者之间是可以互相转换。

public static void main(String[] args) {
        String str = "Demo.java";
        System.out.println("是否以指定 的字符串结束:"+ str.endsWith("ja"));
        //str = "";
        System.out.println("判断字符串是否为空内容:"+str.isEmpty());
        System.out.println("判断字符串是否包含指定的内容:"+ str.contains("Demo"));
        System.out.println("判断两个 字符串的内容是否一致:"+ "DEMO.JAVA".equals(str));
        System.out.println("判断两个字符串的内容是否一致(忽略大小写比较):"+ "DEMO.JAVA".equalsIgnoreCase(str));

//转换的方法

char[] buf = str.toCharArray();  //把字符串转换字符数组
        System.out.println("字符数组:"+ Arrays.toString(buf));
        byte[] buf2 = str.getBytes();   //把字符串转字节数组
        System.out.println("字节数组:"+ Arrays.toString(buf2));
    }

字符串操作

String str = "今天晚上不考试";
System.out.println("指定新内容替换旧 的内容:"+ str.replace("不", "要好好"));
        str = "大家-下-午-好";
        String[] arr = str.split("-"); //根据指定的字符进行切割 。
        System.out.println("字符串数组的内容:"+ Arrays.toString(arr));
        str = "广州传智播客";
        System.out.println("指定开始的索引值截取子串:"+ str.substring(2));
        System.out.println("指定开始的索引值截取子串:"+ str.substring(2,6)); //包头不包尾  注意:截取的内容是包括开始的索引值,不包括结束的索引值, 截取的位置是结束的索引值-1.

str = "abC中国";
System.out.println("转大写:" + str.toUpperCase());
str = "AbdfSDD"; 
System.out.println("转小写:"+ str.toLowerCase());

str = "         大家最近        都非常努力            ";
System.out.println("去除字符串首尾的空格:"+ str.trim());

字符串的运用:

package cn.itcsat.string;
/*
需求1:自己实现trim的方法。

需求2: 获取上传文件名  "D:\\20120512\\day12\\Demo1.java"。

需求3:    将字符串对象中存储的字符反序。    新中国好     -----> 好国中新

需求4: 求一个子串在整串中出现的次数 。 

public class Demo6 {
    public static void main(String[] args) {
        String str  ="        大家       好嘛             ";    
        System.out.println(myTrim(str));

        str =  "D:\\20120512\\day12\\Demo1.java";
        getFileName(str);

        str = "新中国好";
        System.out.println("翻转后的字符串:"+ reverse(str));

        str = "abcjavaabcjavaphpjava";  //java
        getCount(str, "java");

    }


    //  需求1:自己实现trim的方法。
        public static String myTrim(String str){
            //先转换成字符 数组
            char[] arr = str.toCharArray();
            //定义两个 变量记录开始与结束 的索引值
            int startIndex = 0 ;
            int endIndex = arr.length -1;
            //确定开始 的索引值
            while(true){
                if(arr[startIndex]==' '){
                    startIndex++;
                }else{
                    break;
                }
            }
            //确定结束 的索引值:
            while(true){
                if(arr[endIndex]==' '){
                    endIndex--;
                }else{
                    break;
                }
            }
            //截取子串返回
            return str.substring(startIndex,endIndex+1);        
        }


}

    //需求2: 获取上传文件名  "D:\\20120512\\day12\\Demo1.java"。
    public static void getFileName(String path){
        int index = path.lastIndexOf("\\");
        String fileName = path.substring(index+1);
        System.out.println("文件名:"+ fileName);
    }
        //反转
    public static String reverse(String str){
        char[] arr = str.toCharArray();
        for(int startIndex = 0 , endIndex=arr.length-1 ; startIndex<endIndex; startIndex++,endIndex--){
                char temp = arr[startIndex];
                arr[startIndex] = arr[endIndex];
                arr[endIndex] = temp;
        }
        //使用字符数组构建一个字符串。
        return new String(arr);
    }
    //统计子串出现 的次数
    public static void getCount(String str,String target){
        int count = 0 ; //用于记录出现的次数
        int fromIndex  = 0; // 记录从那个索引值开始寻找目标子串
        while((fromIndex = str.indexOf(target, fromIndex))!=-1){
            //如果indexof方法返回 的不是-1,那么就是已经找到了目标 元素。
            count++;
            fromIndex = fromIndex+target.length();
        }
        System.out.println("出现的次数:"+ count);
    }

字符串还有个StringBuffer
如果需要频繁修改字符串 的内容,建议使用字符串缓冲 类(StringBuffer)。

笔试题目:使用Stringbuffer无 参的构造函数创建 一个对象时,默认的初始容量是多少? 如果长度不够使用了,自动增长多少倍?
StringBuffer 底层是依赖了一个字符数组才能存储字符数据 的,该字符串数组默认 的初始容量是16, 如果字符数组的长度不够使用 死,自动增长1倍。

容器的具备 的行为:增加 删除 修改 查看 判断

//先使用StringBuffer无参的构造函数创建一个字符串缓冲类。
            StringBuffer sb = new StringBuffer(); 
            sb.append("java");
            sb.append("java");
            sb.append("java");
            sb.append("java");
            sb.append("java");
    StringBuffer对象和String对象之间的互转的代码如下:
             String s = “abc”;
             StringBuffer sb1 = new StringBuffer(“123”);
             StringBuffer sb2 = new StringBuffer(s);   //String转换为StringBuffer
             String s1 = sb1.toString();              //StringBuffer转换为String

单行用加号拼接字符串是没有性能损失的,java编译器会隐式的替换成stringbuilder,
但在有循环的情况下,编译器没法做到足够智能的替换,仍然会有不必要的性能损耗,
因此,用循环拼接字符串的时候,还是老老实实的用stringbuilder吧。

String,StringBuffer与StringBuilder的区别??

注意:

1、String类型的字符串对象是不可变的,一旦String对象创建后,包含在这个对象中的字符系列是不可以改变的,直到这个对象被销毁。

2、StringBuilder和StringBuffer类型的字符串是可变的,不同的是StringBuffer类型的是线程安全的,而StringBuilder不是线程安全的

3、如果是多线程环境下涉及到共享变量的插入和删除操作,StringBuffer则是首选。如果是非多线程操作并且有大量的字符串拼接,插入,删除操作则StringBuilder是首选。毕竟String类是通过创建临时变量来实现字符串拼接的,耗内存还效率不高,怎么说StringBuilder是通过JNI方式实现终极操作的。

4、StringBuilder和StringBuffer的“可变”特性总结如下:

(1)append,insert,delete方法最根本上都是调用System.arraycopy()这个方法来达到目的

(2)substring(int, int)方法是通过重新new String(value, start, end -
start)的方式来达到目的。因此,在执行substring操作时,StringBuilder和String基本上没什么区别。

单线程的时候基本上用StringBuild就对了主要有append和insert等方法

StringBuffer的方法
//先使用StringBuffer无参的构造函数创建一个字符串缓冲类。
StringBuffer sb = new StringBuffer();
sb.append(“abcjavaabc”);
/*
添加
sb.append(true);
sb.append(3.14f);
插入

    sb.insert(2, "小明");
    */

    /*
    删除
    sb.delete(2, 4); //  删除的时候也是包头不包尾
    sb.deleteCharAt(3); //根据指定 的索引值删除一个字符

    修改  
    sb.replace(2, 4, "陈小狗");

    sb.reverse(); // 翻转字符串的内容

    sb.setCharAt(3, '红');

    String subString = sb.substring(2, 4);
    System.out.println("子串的内容:"+ subString);

    查看

    int index = sb.indexOf("abc", 3);
    System.out.println("索引值为:"+index);

    sb.append("javajava");
    System.out.println("查看字符数组的长度:"+ sb.capacity());
    */

    System.out.println("存储的字符个数:"+sb.length());
    System.out.println("索引指定的索引值查找字符:"+sb.charAt(2) );
    System.out.println("字符串缓冲类的内容:"+ sb);

    String content = sb.toString();
    test(content);
String s1 = "abc";

String s2 = "a";

String s3 = "bc";

String s4 = s2 + s3;

System.out.println(s1 == s4);

结果为: false

原理是: 字符串相加是通过StringBuffer类的append()和toString()实现的, 而toString()返回的字符串是通过构造函数创建的.

toString()是转换为String类型
如果是引用对象那么就值就是完整类名@地址
如果是String就是输出结果
而且 System.out.println 会自动调用toString()
StringBuilder 可以实现字符串添加 没有创建新的字符串 toString返回的是字符串 是new出来的 在堆中

上一篇:go的同步模型


下一篇:增大模型依然有用,DeepMind用2800亿参数的Gopher,测试语言系统极限