黑马程序员_十 【String】【StringBuffer】【基本数据包装类】

深入解析Java字符串与缓冲区技术
本文详细阐述了Java中的String、StringBuffer、StringBuilder类的特性与使用方法,包括字符串的基本操作、转换、替换、切割等核心功能,以及如何在实际编程中灵活运用这些技术。同时对比了StringBuffer与StringBuilder的区别,强调了StringBuilder在现代开发中的优势。

 

--------------------- android培训java培训、java学习型技术博客、期待与您交流! -------------------

 

【Sing】【StringBuffer】【StringBuilder】【基本类型包装类】

 1  String 

String类的定义:

public final class String  没有子类,因为用final修饰了

String 是描述字符串的类Java 程序中的所有字符串字面值(如"abc")都作为此类的实例实现。也就是说只要用“”双引号引起来的,都是一个String的一个具体对象

查看API发现String有很多构造函数,其中就有空参数构造函数

String s =new String();

String s =  ;

上面两条指令一个意思,因为第一个比较麻烦,一般都是用第二种。

String s1 = abcs1是一个类类型变量,所以abc是一个类类型变量

字符串的特点是一旦被初始化,就不能改变。字符串常量就是这个意思,固定不变的一个值

如果再输入s1 = kk这个时候如果输出s1就是kk。这个时候上面的abc没有改变,只不过s1的地址指向了kk,上面的abc还是常量

String s2=new  String(abc);

1.  s1==s2

2.  s1.equals(s2)

上面的第一个为false,第二个true因为s2new出来的对象,new String(abc)实质是创建了两个对象,s2指向了该对象;而第二个equals判断是内存中的地址值,s1s2指向的是同一个地址。String类复写了Object类中equals方法,该方法用于判断字符串是否相同。

String s1 = abc

String s2=new  String(abc);

String s3 = abc

S1==s2   输出结果是false

S1==s3   输出结果是true

S1s2的区别

S1在内存中有一个对象,s2在内存中有两个对象。就这一个区别。S2有两个对象是因为一个常量abc,另一个是new String,分别存在于常量池和堆内存中,两个对象

其实内存块里面有个常量池,字符串会存放在常量池里面

s1==s3是因为s3建立的时候,发现内存中已经有abc了,所以就不单独再开空间了。所以相等

字符串四个特点

|--字符串类型的数据是一个对象

|--是一个常量,不能被改变

|--s1s2的区别

4|--s1.equals(s2),字符串类中覆写了object类中的equals方法,用来判断字符串内容是否相同

扩展知识:

==判断的是两个变量或实例是否是指向同一个内存地址;
equals是判断两个变量或实例所指向的内存空间的值是不是相同;
instanceof是判断两个变量(引用)是否是同一个类类型的。

(1)对于字符串变量来说,使用==equals()方法比较字符串时,其比较方法不同。
==比较两个变量本身的值,即两个对象在内存中的首地址。
equals()比较字符串中所包含的内容是否相同。
比如:
String s1,s2,s3 = "abc", s4 ="abc" ;
s1 = new String("abc");
s2 = new String("abc");
那么:
s1==s2   是 false      //两个变量的内存地址不一样,也就是说它们指向的对象不 一样,
故不相等。
s1.equals(s2) 是 true    //两个变量的所包含的内容是abc,故相等。
注意:
如果:        StringBuffer s1 =new StringBuffer("a");
                StringBuffer s2 = new StringBuffer("a");
 

结果:      s1.equals(s2)  //false
解释:StringBuffer类中没有重新定义equals这个方法,因此这个方法就来自Object类, 而Object类中的equals方法是用来比较地址的,所以等于false.
注意:
对于s3s4来说,有一点不一样要引起注意,由于s3s4是两个字符
串常量所生成的变量,其中所存放的内存地址是相等的,
所以s3==s4true(即使没有s3=s4这样一个赋值语句)
2)对于非字符串变量来说,"==""equals"方法的作用是相同的都是用来比较其
对象在堆内存的首地址,即用来比较两个引用变量是否指向同一个对象。
例子:
class A
{

      A obj1   =   new  A();

      A obj2   =   new  A();

}
那么:obj1==obj2false
            obj1.equals(obj2)false
但是如加上这样一句:obj1=obj2;
那么  obj1==obj2  true
          obj1.equals(obj2) true
总之:equals方法对于字符串来说是比较内容的,而对于非字符串来说是比较

其指向的对象是否相同的。
     == 比较符也是比较指向的对象是否相同的也就是对象在对内存中的的首地址。
String类中重新定义了equals这个方法,而且比较的是值,而不是地址。所以是true


equals方法和instanceof 的区别:
instanceof操作符用于判断一个引用类型所引用的对象是否是一个类的实例 .对于引用类型变量,Java 编译器只根据变量被先生声明的类去编译。
instanceof 左边操作元被显式声明的类型与右边操作元必须是同种类或者有继承关系,即位于继承树的同一个继承分支上,否则编译出错.
Object 类的 equals() 方法的比较规则为:当参数 obj 引用的对象与当前对象为同一个对象时,就返回true,否则返回false

JDK中有一些类覆盖了 Object 类的equals()方法,它们的比较规则为:
如果两个对象的类型一致,并且内容一致,则返回true
这些类包括:java.io.Filejava.util.Datejava.lang.String、包装类(java.lang.Integerjava.lang.Double)
如果是自己定义的类的话,可以复写equals()方法,自己定义比较规则
Java语言对equals()的要求如下,这些要求是必须遵循的,以下几点也算是和instanceof 的区别: 
|----对称性:如果x.equals(y)返回是true,那么y.equals(x)也应该返回是true。 
|----反射性:x.equals(x)必须返回是true。 
|---- 类推性:如果x.equals(y)返回是true,而且y.equals(z)返回是true,那么z.equals(x)也应该返回是true。 
|---- 还有一致性:如果x.equals(y)返回是true,只要xy内容一直不变,不管你重复x.equals(y)多少次,返回都是true。 
|---- 任何情况下,x.equals(null),永远返回是falsex.equals(x不同类型的对象)永远返回false。 

String中的方法:

常见字符串操作:

1.   获取

|----字符串中包含的字符数,也就是字符串的长度int length()(数组有长度但是是属性,通过arr.length返回这个属性来完成。而这里是一个方法,带(),功能是获取长度。)

|----根据位置获取位置上某个字符。

  CharcharAtint index):

|----根据换字符获取该字符串中的位置。

IntindexOf (int ch):返回的是ch在字符串中第一次出现的位置。当访问到字符串中不存在的角标时会发生StringIndexOutOfBoundsException。字符角标越界。

int indexOf(intch, int fromIndex) :fromIndex指定位置开始,获取ch在字符串中出现的位置。如果ch值没有出现在字符串中,输出的值为-1

int indexOf(String str):返回的是str在字符串中第一次出现的位置。

intindexOf(String str, int fromIndex) :fromIndex指定位置开始,获取str在字符串中出现的位置。String型,字符串应该用单引号a

int lastIndexOf(int ch):反向索引,输出的结果还是正常的角标,只不过系统会从后面往前数数。注意这里是int型,字符串a应该加双引号a

简单例子:

/*需求:统计一个字符串中大写字母,小写字母,以及数字的个数。  

思路: 

*       1:接受键盘录入一个字符串。 

*       2:获取每个字符进行判断 

*       3:可以根据对应的ASCII码值进行比较,确定字符类型 

*/  

import java.util.Scanner;  

  

  

10 public class Lianxi {  

11 public static void main(String[] args) {  

12     //定义键盘输入功能  

13     Scanner sc=new Scanner(System.in);  

14     //输入字符串  

15     System.out.println("请输入字符串:");  

16     //接收字符串  

17     String str=sc.nextLine();  

18     //定义计数器  

19     int big=0;  

20     int num=0;  

21     int small=0;  

22     //遍历字符判断类型  

23     for(int x=0;x<str.length();x++){  

24         char ch=str.charAt(x);  

25         if(ch>='a'&&ch<='z'){  

26             small++;  

27         }  

28         else if(ch>='A'&&ch<='Z'){  

29             big++;  

30         }  

31         else{  

32             num++;  

33         }  

34     }  

35     System.out.println("大写字母个数:"+big);  

36     System.out.println("小写字母个数:"+small);  

37     System.out.println("数字个数:"+num);  

38 }  

39 }  

2,判断。

     |----字符串中是否包含某一个子串。(两个方法)

           boolean contains(str):

           特殊之处重要掌握:indexOf(str):可以索引str第一次出现位置,如果返回-1.表示该str不在字符串中存在。所以,也可以用于对指定判断是否包含。

                      if(str.indexOf("aa")!=-1)

           而且该方法即可以判断,有可以获取出现的位置。

     |----字符中是否有内容。

           boolean isEmpty(): 原理就是判断长度length()是否为0.

     |---- 字符串是否是以指定内容开头。

           boolean startsWith(str);

     |---- 字符串是否是以指定内容结尾。

           boolean endsWith(str);

     |---- 判断字符串内容是否相同。复写了Object类中的equals方法。不忽略大小写           boolean equals(str);

     |---- 判断内容是否相同,并忽略大小写。

           boolean equalsIgnoreCase();

3,转换。

  |----将字符数组转成字符串。

      构造函数:String(char[])

      String(char[],offset,count):将字符数组中的一部分转成字符串。

      Offset是角标,count是个数,从offset开始后面的count数目的数组内容转换成字符串。如果有对象建立,放到新的对象里面

char[] arr = {'a','b','c','d','e','f'};

           String s= new String(arr,1,3);

           sop("s="+s);

           输出结果是s=bcd

      静态方法:

           static String copyValueOf(char[]);

           static String copyValueOf(char[]data, int offset, int count)

           static String valueOf(char[]):

           要回去找这些方法并使用。静态的方法是因为方法内部没有特殊变量

  |----将字符串转成字符数组。**

           char[] toCharArray():

  |---- 将字节数组转成字符串。

                 String(byte[])一定要记住这个函数

                 String(byte[],offset,count):将字节数组中的一部分转成字符串。

  |---- 将字符串转成字节数组。

                 byte[]  getBytes():

  |---- 将基本数据类型转成字符串。

           static String valueOf(int)

           static String valueOf(double)

           //3+"";//String.valueOf(3);这两个的意思是一样的。3和空字符,后者比较准确,但比较麻烦,一般写前者。

           特殊:字符串和字节数组在转换过程中,是可以指定编码表的。

简单例子:

40 /* 

41  * 需求:获取键盘录入的字符串,请把这个字符串的首字母改为大写,其他的字母小写。 

42  *  

43  * 思路: 

44  * 1.键盘录入字符串 

45  * 2.截取字符串的第一个字母及之后的字符串 

46  * 3.转换首字母并连接字符串 

47  */  

48 import java.util.Scanner;  

49   

50 public class Test {  

51     public static void main(String[] args) {  

52         // 封装键盘录入字符串  

53         Scanner sc = new Scanner(System.in);  

54         System.out.println("请输入字符串:");  

55         String str = sc.nextLine();  

56         // 截取字符串  

57         String str1 = str.substring(01);  

58         String str2 = str.substring(1, str.length());  

59         // 转换大小写  

60         String str3 = str1.toUpperCase();  

61         // 连接字符串  

62         String str4 = str3.concat(str2);  

63         System.out.println("str4=" + str4);  

64     }  

4,替换

      String replace(oldchar,newchar);

示例:

      String s = "Hello Java";

      String s1 = s.replace(a,n);

      Sop(s);

      Sop(s1);

输出结果是Hello JavaHello Jnvn。因为s字符串用final修饰,不会变的。调用replace函数以后赋值给了s1

如果用q替换n呢?没有q,所以返回的是原字符串

5,切割

      String[] split(regex);

示例: public static void method_split()

      {

           String s ="zhagnsa,lisi,wangwu";

           String[] arr  = s.split(",");//建立一个字符串数组,arr,用来放s切割后的字符串。

           for(int x = 0; x<arr.length; x++)

           {

                 sop(arr[x]);//打印数组

           }

      }

注意这是个分割函数,用分割,这个逗号是拿不到的。

简单例子:

65 /* 

66  * 需求:对字符串中字符进行自然顺序排序:"basckd",结果是:"abcdks" 

67  *  

68  * 思路: 

69  * 1.把字符串转换成字符数组 

70  * 2.把字符数组排序 

71  * 3.把字符数组转换成字符串 

72  */  

73 public class Demo {  

74     public static void main(String[] args) {  

75         // 输入字符串  

76         String str1 = "basckd";  

77         // 转换成字符数组  

78         char[] chs = str1.toCharArray();  

79         // 定义排序功能,选择排序  

80         selectSort(chs);  

81         // 将字符数组转换成字符串  

82         String str2 = String.valueOf(chs);  

83         System.out.println(str2);  

84     }  

85   

86     private static void selectSort(char[] chs) {  

87         for (int x = 0; x < chs.length - 1; x++) {  

88             for (int y = x + 1; y < chs.length; y++) {  

89                 if (chs[x] > chs[y]) {  

90                     char temp = chs[x];  

91                     chs[x] = chs[y];  

92                     chs[y] = temp;  

93                 }  

94             }  

95         }  

96   

97     }  

98 }  

6,子串。获取字符串中的一部分。

      String substring(begin);

      String substring(begin,end);

示例     String s ="abcdef";

      sop(s.substring(2));//从指定位置开始到结尾。如果角标不存在,会出现字符串角标越界异常。

      sop(s.substring(2,4));//包含头,不包含尾。

上面输出的结果是cdefcd。获取所有的数组的就是s.substring(0,s.length());

7,转换,去除空格,比较。

     |---- 将字符串转成大写或则小写。

            String toUpperCase();

            String toLowerCase();

     |----将字符串两端的多个空格去除。

           String trim();

     |---- 对两个字符串进行自然顺序的比较。

           int compareTo(string);

 2  StringBuffer、StringBuilder类 

StringBuffer是字符串缓冲区。是一个容器。可以对字符串内容进行增删。字符串的组成原理就是通过该类实现的。publicfinal class StringBuffer同样被final修饰,不能修改

特点:

1,长度是可变化的。

2,可以字节操作多个数据类型。

3,最终会通过toString方法变成字符串。

数组的个数和类型是固定的,所以当数值类型和个数不固定时一般都用StringBuffer

特点:

1,长度是可变化的。

2,可以字节操作多个数据类型。

3,最终会通过toString方法变成字符串。

1,存储。

      StringBuffer append():将指定数据作为参数添加到已有数据结尾处。

Byte short没有,因为接收int无法提升

      StringBuffer insert(index,数据):可以将数据插入到指定index位置。

示例:StringBuilder sb = new StringBuffer ();

      StringBuffer sb1 =sb.append(34)

      Sop(sb.toString());

      Sop(sb1.toString());

此时输出结果一样,并且sb==sb1原因是StringBuffer是一个容器,放了sb,改变了sbsb1,还是那个容器并没有变。所以改变后两者相等。并且可以这样使用

      Sb.appen(abc).apend(34);方法调用链,方法使用后返回的仍然为原来的对象可以继续调用方法

      Sb.insert(1,qq)从第一位后插入qq这个字符串

2,删除。

      StringBuffer delete(start,end):删除缓冲区中的数据,包含start,不包含end

      StringBuffer deleteCharAt(index):删除指定位置的字符。

      清空缓冲区的命令:sb.delete(0,sb.length());最大角标是length-1,因为这个delete命令包含头不包含尾,所以是sb.length()

3,获取。

      char charAt(int index)

      int indexOf(String str)

      int lastIndexOf(String str)

      int length()

      String substring(int start, int end)

4,修改。

      StringBuffer replace(start,end,string);

      void setCharAt(int index, char ch) ;

5,反转。

      StringBuffer reverse();

6,将缓冲区中指定数据存储到指定字符数组中。

      void getChars(int srcBegin, int srcEnd,char[] dst, int dstBegin)

JDK1.5 版本之后出现了StringBuilder.

StringBuffer与StringBuilder的区别:StringBuffer是线程安全的,效率低;StringBuilder是线程不安全的,效率高

StringBuffer是线程同步。

StringBuilder是线程不同步。

以后开发,建议使用StringBuilder

升级三个因素:

1,提高效率。

2,简化书写。

3,提高安全性。

简单例子:

99 /* 

100  * 将一个int数组变成字符串 

101  * 思路:1.建立StringBuilder对象 

102  * 2.调用append方法添加 

103  * 3.返回字符串 

104  */  

105 public class Lianxi {  

106     public static void main(String[] args) {  

107         int[] arr = { 37905 };  

108         String str = arrayToString(arr);  

109         System.out.println(str);  

110     }  

111   

112     private static String arrayToString(int[] arr) {  

113         // 建立StringBuilder对象  

114         StringBuilder sb = new StringBuilder();  

115         // 遍历数组,添加字符串  

116         sb.append("[");  

117         for (int x = 0; x < arr.length; x++) {  

118             if (x != arr.length - 1) {  

119                 sb.append(arr[x] + ",");  

120             } else {  

121                 sb.append(arr[x] + "]");  

122             }  

123         }  

124         return sb.toString();  

125     }  

126 }  


 3  基本数据类型包装类 

在许多情况下包装与解包装是由编译器自行完成的(在这种情况下包装成为装箱,解包装称为拆箱); 
可理解理解自动装箱就可以简单的理解为将基本数据类型封装为对象类型,来符合java的面向对象;

 例如用int

Integer num = 10; //声明一个Integer对象 此声明就是用到了自动的装箱:解析为

Integer num = new Integer(10);以上就是一个很好的体现,因为10是属于基本数据类型的,原则上它是

 不能直接赋值给一个对象Integer的,但jdk1.5后你就可以进行这样的声明,这就是自动装箱的魅力 
自动将基本数据类型转化为对应的封装类型。成为一个对象以后就可以调用对象所声明的所有的方法 

自动拆箱:故名思议就是将对象重新转化为基本数据类型:
Integer num = 10;//装箱  
int num1 = num;//拆箱 
自动拆箱有个很典型的用法就是在进行运算的时候:因为对象时不能直接进行运算的,而是要转化为基本数据类型后才能进行加减乘除 。 


Integer num = 10; 
//进行计算时隐含的有自动拆箱 
System.out.print(num--);

 在-128~127 之外的数 
                 Integer num1 = 297; Integer num2 = 297; //-128~127 之外的数
                System.out.println("num1==num2: "+(num1==num2)); //num1==num2: false 
 
                 Integer num3 = 97; Integer num4 = 97;// -128~127 之内的数
                 System.out.println("num3==num4: "+(num3==num4)); //num3==num4: true

说明:

加大对简单数字的重利用,java定义:在自动装箱时对于值从128127之间的值,它们被装箱

这就归结于java对于Integer与int的自动装箱与拆箱的设计,是一种模式:叫享元模式(flyweight)

Integer对象后,会存在内存中被重用,始终只存在一个对象 而如果超过了从128127之间

的值,被装箱后的Integer对象并不会被重用,即相当于每次装箱时都新建一个 Integer对象。

自动装箱拆箱不仅在基本数据类型中有应用,在String类中也有应用
               String str = "sl"; 
               //代替下面的声明方式 
               String str = new String("sl");

 

     例题 1、 Integer a = new Integer(100);     Integer b = 100; Integer c =100; int d = 100;abcd这四个数通过==equals方法,进行比较,都哪些结果是true,哪些是false?

public class T1 {
    
 public static void main(String[] args) {
   Integer a = new Integer(100);
   Integer b = 100;     
   Integer c =100;     
   int d = 100;
 // 下面是测试证明==
   System.out.println(d==a);  //true
   System.out.println(d==b);   //true
   System.out.println(d==c);    //true
   System.out.println(a==b) ;//false
   System.out.println(a==c);//false
   System.out.println(b==c);//true
 // 下面是测试证明equals
    // System.out.println(d.equals(a));//不能调用基本类型 int 的 equalsInteger
    // System.out.println(d.equals(b));//不能调用基本类型 int 的 equalsInteger
    // System.out.println(d.equals(c));//不能调用基本类型 int 的 equalsInteger
   System.out.println(b.equals(c));//true
   System.out.println(a.equals(b));//true
   System.out.println(a.equals(c));//true
   System.out.println(a.equals(d));//true  
   System.out.println(b.equals(d));//true
   System.out.println(c.equals(d));//true
 }

}

讲解:

1.  d==a;d==b;d==c;true

            因为JDK1.5版本以后的新特性可以可以Integer对象自动拆箱成为int型变量,所以结果为true
2.   a==ba==c;false

          因为bc为自动装箱后才生的两个新对象,该对象与a不是同一对象
3.  b==ctrue

           因为他们都是由int型变量自动装箱而来,他们的比较是先拆箱还原成int型变量之后才进行比较由于dint型变量,不是对象,没有equals方法,所以不能和a,b,c对象做比较。
4.   b.equals(c);a.equals(b);a.equals(c);都为true

          因为equals只针对对象的内容进行比较
5.  a.equals(d);b.equals(d);c.equals(d) 都为true

           因为此时的int型变量被自动装箱为Integer对象,而equals只针对对象的内容进行比较

 

总结:

操作字符串的方法有很多,刚开始学的时候感觉知识点太多了,但学完一回顾大致也就分为四类,增删改查.StringBuffer和StringBuilder的区别就在于是否是线程安全,线程安全的有同步代码,每次运行都需要判断同步锁,效率相比之下也就比较低

基本数据类型:

1.在进行编译时,编译器再自动根据您写下的语句,判断是否进行自动装箱动作。

在上例中integer参考的会是Integer类的实例。同样的动作可以适用于 boolean

byteshortcharlongfloatdouble等基本数据类型,分别会使用对应的打

包类型(Wrapper Types)BooleanByteShortCharacterLongFloatDouble

2.JAVA中利用"=="比较变量时,系统使用变量在""中所存的值作为比较的依据。
基本数据类型在""中存的是其内容值,而对象类型在""中存的是地址,这些地址指向""中的对象。==只针对变量的值;equals只针对对象的内容

 

 

 

本篇博文结束!




                                                                                                   @感谢老师的辛苦批阅

 

 

内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值