主頁 > 後端開發 > Java基礎語法(九)——String類

Java基礎語法(九)——String類

2021-06-09 21:48:09 後端開發

文章目錄

  • Java基礎語法(九)——String類
  • 一、定義方式
  • 二、記憶體
  • 三、字串比較相等
  • 四、字串常量池
  • (1) 直接賦值
  • (2)采用構造方法
  • (3)intern 的使用
  • 五、理解字串不可變
  • 六、字符、位元組、字串
  • (1)字符與字串
  • (2)位元組與字串
  • (3) 小結
  • 七、字串的常見操作
  • (1)字串比較
  • (2)字串查找
  • (3)字串替換
  • (4)字串拆分
  • (5)字串截取
  • (6)其他操作方法
  • (7)字串操作練習題
    • 1.逆置字串
    • 2.翻轉字串
  • 八、StringBuffer 和 StringBuilder
  • (1)append 方法
  • (2)注意
  • (3)區別
  • 完!

Java基礎語法(九)——String類


本次內容介紹大綱


在這里插入圖片描述

??字串是我們以后作業中非常常用到的型別. 使用起來都非常簡單方便, 我們一定要使用熟練,


??那么C語言中是否有字串型別? 答案是 “ 沒有 ” !!


??char *p = " hello";


??那么p 的型別是一個字串型別么? 不是,p是一個指標!!


??而在 Java當中 是有 字串型別的——String


一、定義方式


創建字串的方式有很多種,常見的構造 String 的方式如以下:

方式一:直接賦值法

String str1 = "hello";

方式二: new String()

String str2 = new String("hello");

方式三:創建一個字符陣列ch,new String ( ch )

char chs[] = {'h','e','l','l','l','o'};
String str3 = new String(chs);

二、記憶體


在此之前我們要先引入一個概念 字串常量池

Sting constant pool 字串常量池 的特性


1.在JDK.7 開始,字串常量池 被挪到堆里了

2.池內的資料不存在重復


??下面我們通過一系列的練習來熟悉 字串常量池以及 字串型別資料在記憶體中的存放,

  public static void main(String[] args) {
       String str1 = "hello";
       String str2 = new String("hello");
        System.out.println(str1 == str2);

        String str3 = "hello";
        System.out.println(str1 == str3);
    }

??我們來看這樣的代碼,str 代表的是參考\地址,請判斷 兩次列印分別是什么?


我們來看結果


在這里插入圖片描述


??這個結果說明 str1 和 str2存放的地址是不一樣的, str1 和 str3 存放的地址是一樣的,


??好的,為什么是這樣的結果呢?我們來看一下這幾個字串型別變數的記憶體,

在這里插入圖片描述

??"hello"如果存放在常量池當中,就會占用記憶體,假如這塊空間的地址為111,那么str1中存放的就是111.

??str2 new一個String物件,那么肯定在堆上開辟記憶體,假設記憶體地址是888,在這個String 物件中,存在一個value[] 保存著 orginal傳入的字串,這個val ==“hello”,因為在字串常量池中已經有了"hello",所以val 直接指向 常量池中的"hello".但是str2 指向的依然是 888在堆中的空間,

在這里插入圖片描述
在這里插入圖片描述

所以 str1 不等于 str2,


??之后呢,str3 也等于"hello",他也準備把hello放在常量池當中.此時常量池中已經存在"hello",那么之后str3 在存放"hello"地址的時候,就指向的是常量池中原來hello的地址,


所以 str1 等于 str3


再看一組練習

    public static void main(String[] args) {

        String str1 = "hello";
        String str2 = "hel"+"lo";
        System.out.println(str1==str2);

        String str3 = new String("hel")+"lo";
        System.out.println(str1==str3);

    }

請判斷兩次列印的結果…

結果如下:

在這里插入圖片描述
下面我們來分析,這組代碼中str變數的記憶體存放

在這里插入圖片描述

str1 指向字串常量池中的 “hello”

??str2 是"hel"與"lo" 組合而成的,常量在編譯的時候就已經確定了,所以在編譯時,已經被處理為"hello",所以也指向 常量池中的"hello",


所以 str1 等于 str2


??str3 首先new 了一個String(“hel”)物件,在堆中開辟一塊空間,這個物件中的"hel"同時存放在常量池中,之后又在常量池中開辟一塊空間存放 “lo”,兩塊部分之間的"+",將 String 的物件 與常量池中的 "lo"結合在堆中再次開辟一塊新的空間,這塊記憶體中的val ==“hello”,str3指向的是合并之后的物件 ,地址為999.

所以 str1 不等于 str3.


再看一組練習

 public static void func(String str,char[] array){
        str = "abcdef";
        array[0] = 'g';
    }

    public static void main(String[] args) {
        String str1 = "hello";
        char[] val = {'a'};
        System.out.println(str1);
        System.out.println(Arrays.toString(val));
        func(str1,val);
        System.out.println("=================");
        System.out.println(str1);
        System.out.println(Arrays.toString(val));
    }

??請看一下,我們將String str 作為引數,改變str 的內容,以及傳入 陣列 val 改變 陣列元素,其列印結果是什么?


在這里插入圖片描述

??我們看到 String str 的內容并未改變,但是陣列 val 的元素卻改變了,

我們從記憶體的角度來分析,

在這里插入圖片描述

??str1 指向字串常量區的"hello",地址為888

??val 作為陣列參考,指向堆中開辟的陣列空間,地址為777

??str 作為函式的形參,接收str1實參的值,也就是888,此時str指向常量區的”hello“,但是在方法的內部,str = “abcde”,在字串常量區中有開辟一塊"abcde"的記憶體,地址為000,最后 str 存放的地址為000.

??array 作為函式的形參,接收val 實參的值,也就是777,此時array 指向堆中 開辟的陣列空間,此時通過array 來改變陣列元素的內容,最終 改變的也同樣是val 實參的內容.


三、字串比較相等


如果現在有兩個int型變數,判斷其相等可以使用 == 完成,

str1 = "world";
System.out.println(str2);
// 執行結果
//Hello
int x = 10 ;
int y = 10 ;
System.out.println(x == y); 
// 執行結果
//true

如果說現在在String類物件上使用 == ?


代碼1

String str1 = "Hello";
String str2 = "Hello"; 
System.out.println(str1 == str2); 
// 執行結果
//true 

看起來貌似沒啥問題, 再換個代碼試試, 發現情況不太妙.


代碼2

String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1 == str2);
// 執行結果
//false

??在上面的幾個練習中,我們 用 str1 == str2 比較的是兩個字串的參考/地址,如果比較字串里面的內容,我們需要用到 equals 方法,


 public static void main(String[] args) {
        String str1 = "hello";
        String str2 = new String("hello");
        
        System.out.println(str1==str2);          //比較的是參考
        System.out.println(str1.equals(str2));   //比較 str1 和 str2 字串的內容
        
        String str3 = "hello";
        System.out.println(str1.equals(str3));   //比較 str1 和 str3 字串的內容
    }

最后的列印結果


在這里插入圖片描述


列印的結果符合字串的內容比較,

常用的比較方式:

我們再來看一種情況,

  public static void main(String[] args) {
        String str1 = null;
        String str2 = "hello";
        System.out.println(str1.equals(str2));
    }

這時候運行程式,就會出現以下情況:

在這里插入圖片描述


空指標例外,因為 null. 任何方法都會出現例外,

所以一定要保證 str1 不能為null,

那么如果我們改一下,

public static void main(String[] args) {
        String str1 = null;
        String str2 = "hello";
        System.out.println(str2.equals(str1));
    }

??所以我們知道 equals(),括號里可以是null,但是 點之前一定不能是 null.

public static void main(String[] args) {
        String str1 = "hello";

        System.out.println(str1.equals("hello"));  // 方式1
        System.out.println("hello".equals(str1));  // 方式2
    }

??當我們寫代碼遇到以上的情況時,我們應該盡量選方式2,這樣保證 equals之前一定不為null,以防出現例外.


四、字串常量池


??在上面的例子中, String類的兩種實體化操作, 直接賦值和 new 一個新的 String.


(1) 直接賦值


System.out.println("Hello".equals(str));  // 執行結果 false
String str1 = "hello" ;
String str2 = "hello" ; 
String str3 = "hello" ; 
System.out.println(str1 == str2); // true
System.out.println(str1 == str3); // true
System.out.println(str2 == str3); // true

String類的設計使用了共享設計模式

在JVM底層實際上會自動維護一個物件池(字串常量池)

??如果現在采用了直接賦值的模式進行String類的物件實體化操作,那么該實體化物件(字串內容)將自動保存到這個物件池之中.

??如果下次繼續使用直接賦值的模式宣告String類物件,此時物件池之中如若有指定內容,將直接進行參考

??如若沒有,則開辟新的字串物件而后將其保存在物件池之中以供下次使用


理解 “池” (pool)

??“池” 是編程中的一種常見的, 重要的提升效率的方式, 我們會在未來的學習中遇到各種 “記憶體池”, “執行緒池”, “資料庫連接池” …然而池這樣的概念不是計算機獨有, 也是來自于生活中.
??舉個栗子:現實生活中有一種女神, 稱為 “綠茶”, 在和高富帥談著物件的同時, 還可能和別的屌絲搞曖昧. 這時候這個屌絲被稱為 “備胎”. 那么為啥要有備胎? 因為一旦和高富帥分手了, 就可以立刻找備胎接盤, 這樣 效率比較高.如果這個女神, 同時在和很多個屌絲搞曖昧, 那么這些備胎就稱為 備胎池.


(2)采用構造方法


類物件使用構造方法實體化是標準做法,分析如下程式:


String str = new String("hello");

在這里插入圖片描述


這樣的做法有兩個缺點:


1.??如果使用String構造方法就會開辟兩塊堆記憶體空間,并且其中一塊堆記憶體將成為垃圾空間(字串常量 “hello” 也是一個匿名物件, 用了一次之后就不再使用了, 就成為垃圾空間, 會被 JVM 自動回收掉).

2.??字串共享問題. 同一個字串可能會被存盤多次, 比較浪費空間.


(3)intern 的使用

String str1 = "hello";
String str2 = new String("hello").intren();

??從上面的由 構造方法定義字串,我們會浪費記憶體空間,而這里有一個方法 ,叫做intern(),手動入池,


那這是什么意思呢?


??這是先看一下傳入構造方法的字串在字串常量池中是否存在,如果有的話,就把常量池中的參考傳給當前的參考型別變數,

在這里插入圖片描述

綜上所述,我們一般使用 直接賦值法來 創建 String 物件,

在這里插入圖片描述

我們再來看這樣一組代碼,來畫一下他的記憶體結構

在這里插入圖片描述

??在第一步的代碼中,new 了兩個字串"1",在堆中創建了兩個物件,指向常量池中的"1",拼接在一起,s3.interb(),s3手動入池,“11"在池中沒有,所以就把 堆中的"11"的參考 555 傳入常量池中,s4 指向池中的"11”,而這時池中已經有了"11"的參考,所以s4 指向的就是 s3在入池的參考,

所以結果為 true,
在這里插入圖片描述

所以呢,我們解決了一個疑問

??在常量池當中,可以放 字串的字面值常量,也可以放參考,什么時候放參考,就是類似于上面的那種情況之下,s3.intern(),s3所指向的這個物件在字串常量池中是不存在的,那么入池的時候就把堆中s3的參考放入,


五、理解字串不可變


??字串是一種不可變物件. 它的內容不可改變.這是什么意思呢?

  public static void main(String[] args) {
        String str = "hello" ;
        str = str + " world" ;
        str += "!!!" ;
        System.out.println(str);
    }

??對于這種代碼,乍一看我們以為成功的將str 每次與其他的字串拼接,但是這樣是不可以的, str 原來指向的是"hello",但是 在與" world"拼接之后,又會產生一個新的物件"helll world",再次拼接一個"!!!",那么又會產生一個新的物件"hello world!!!",在記憶體中就會產生多個物件,

在這里插入圖片描述

我們最后需要的是"hello world!!!",但是卻開辟了5塊記憶體空間,

如果在一個回圈中拼接,那么會開辟更多的記憶體空間!!

所以這樣的代碼是極為不可取的!!!

那么如何拼接呢,具體在之后的StringBuff、StringBuilder中介紹,


六、字符、位元組、字串


(1)字符與字串


字串內部包含一個字符陣列,String 可以和 char[] 相互轉換

在這里插入圖片描述

1.字符陣列轉字串
在這里插入圖片描述

    public static void main(String[] args) {
        char[] val = {'h','e','l','l','o'};
        String str = new String(val);
        System.out.println(val);
    }

此時我們 的 str 結果就是 “hello”,同時他也可以再給兩個引數.


2.將部分字符陣列中的內容轉換為字串
在這里插入圖片描述
offset–偏移量
count-- 轉換幾個

 public static void main(String[] args) {
        char[] val = {'h','e','l','l','o'};
        String str = new String(val,1,2);
        System.out.println(str);
    }

此時我們將val 中偏移1個,轉換之后的兩個陣列元素為字串

列印結果應該為 el

運行結果如下:

在這里插入圖片描述


3.將字串中對應索引轉換為字符
在這里插入圖片描述

 public static void main(String[] args) {
        String str = "hello";
        char ch = str.charAt(1);
        System.out.println(ch);
    }

索引從0開始,我們輸入1,所以轉換的為字串中的e

運行結果如下:

在這里插入圖片描述


4.將字串轉換為字符陣列
在這里插入圖片描述

 public static void main(String[] args) {
        String str = "hello";
        char[] val = str.toCharArray();
        System.out.println(Arrays.toString(val));
    }

我們用字符陣列接收 str轉換后的字符,

運行結果如下:


在這里插入圖片描述

??好了,了解了這幾種字符與字串的方法,我們通過幾個練習來繼續熟悉,


練習一

??給定字串一個字串, 判斷其是否全部由數字所組成.

??思路: 將字串變為字符陣列而后判斷每一位字符是否是" 0 “~”‘9’"之間的內容,如果是則為數字.

  public static boolean func1(String str){
        for (int i = 0; i <str.length() ; i++) {
            if(str.charAt(i)>'9' || str.charAt(i)<'0'){
                return false;
            }
        }
        return true;
    }

(2)位元組與字串


??位元組常用于資料傳輸以及編碼轉換的處理之中,String 也能方便的和 byte[] 相互轉換


常用方法:

在這里插入圖片描述

1.位元組陣列轉換為字串
在這里插入圖片描述

  public static void main(String[] args) {
        byte[] bytes = {97,98,99,100};
        String str = new String(bytes);
        System.out.println(str);
    }

運行結果:
在這里插入圖片描述
字串中的內容是位元組陣列與Ascii 碼表中對應的字符,


2.部分位元組陣列的內容轉換為字串
在這里插入圖片描述

  public static void main(String[] args) {
        byte[] bytes = {97,98,99,100};
        String str = new String(bytes,2,1);
        System.out.println(str);
    }

運行結果:

在這里插入圖片描述


3.字串轉換為位元組陣列
在這里插入圖片描述

   public static void main(String[] args) {
        String str = "abcd";
        byte[] bytes = str.getBytes();
        System.out.println(Arrays.toString(bytes));
    }

運行結果:

在這里插入圖片描述


(3) 小結


那么何時使用 byte[], 何時使用 char[] 呢?


??byte[] 是把 String 按照一個位元組一個位元組的方式處理, 這種適合在網路傳輸, 資料存盤這樣的場景下使用. 更適合針對二進制資料來操作.

??char[] 是吧 String 按照一個字符一個字符的方式處理, 更適合針對文本資料來操作, 尤其是包含中文的時候.


七、字串的常見操作


(1)字串比較


??上面使用過String類提供的equals()方法,該方法本身是可以進行區分大小寫的相等判斷,除了這個方法之外,String類還提供有如下的比較操作.

在這里插入圖片描述

1.區分大小寫比較
在這里插入圖片描述

   public static void main(String[] args) {
        String str1 = "abcd";
        String str2 = "Abcd";
        System.out.println(str1.equals(str2));
    }

運行結果:
在這里插入圖片描述
我們常用的equals 方法 是區分大小寫的,這點要注意,


2.不區分大小寫的比較
在這里插入圖片描述

    public static void main(String[] args) {
        String str1 = "abcd";
        String str2 = "Abcd";
        System.out.println(str1.equalsIgnoreCase(str2));
    }

運行結果:

在這里插入圖片描述

??這種不區分大小寫的比較還是很常見的,比如應用于驗證碼上,不區分大小寫,


3.比較兩個字串的大小關系
在這里插入圖片描述

public static void main(String[] args) {
        String str1 = "abcd";
        String str2 = "Abcd";
        System.out.println(str1.compareTo(str2));
    }

運行時結果
在這里插入圖片描述
在這里插入圖片描述
掌握了字串比較相等的方法,下來我們來做一道練習題


比較字串是否相等
在這里插入圖片描述


題解思路:


??將word1 字串陣列的內容都在str1 追加,word2 字串陣列的內容在str2 追加,最終equals 比較str1 str2 字串的內容,相等回傳 true,不等回傳 false.

注意:引數等問題要考慮全面

在這里插入圖片描述

在這里插入圖片描述


(2)字串查找


??從一個完整的字串之中可以判斷指定內容是否存在,對于查找方法有如下定義:

在這里插入圖片描述

判斷一個字串中是否存在子字串
在這里插入圖片描述


我們可以先看一下 contains 方法的原始碼

在這里插入圖片描述
contains 方法的使用

 public static void main(String[] args) {
       String str = "bcdabc";
       boolean flg = str.contains("abc");
        System.out.println(flg);
    }

運行結果

在這里插入圖片描述

所以可判斷在"badabc" 這個字串中存在 這個 “abc” 的子字串,


找到子字串的下標
在這里插入圖片描述


我們先來看一下一個引數的 index 方法的原始碼

在這里插入圖片描述

帶一個引數的 index 方法的使用


    public static void main(String[] args) {
        String str = "ababcabcdabcde";
        int index1 = str.indexOf("abc");
        int index2 = str.indexOf("hello");
        System.out.println(index1);
        System.out.println("============");
        System.out.println(index2);
    }

運行結果:

在這里插入圖片描述

兩個引數的index 方法的使用
在這里插入圖片描述


??在下面我們又看到了一個index 方法,這說明 默認情況下,index 是從0下標開始查找的,如果再給他一個下標引數,那么就從指定的下標位置進行字串查找,


使用:

 public static void main(String[] args) {
        String str = "abcabcdabcdef";
        int index1 = str.indexOf("abc");
        int index2 = str.indexOf("abc",6);
        System.out.println(index1);
        System.out.println("=================");
        System.out.println(index2);
    }

運行結果:

在這里插入圖片描述

從后往前查找到子字串的位置
在這里插入圖片描述


lastIndexOf 是從后向前查找 子字串的位置

lastIndexOf 方法的使用

 public static void main(String[] args) {
        String str = "abcabcdabcdef";
        int index = str.lastIndexOf("abc");
        System.out.println(index);
    }

運行結果:

在這里插入圖片描述
??同時 lastIndexOf 也有兩個引數的方法,從指定下標開始從后向前進行查找,

判斷是否由 引數字串開頭的
在這里插入圖片描述
同時也有兩個引數的方法,從指定位置判斷是否由 指定字串開頭
在這里插入圖片描述


判斷是否由指定字串進行結尾的
在這里插入圖片描述


(3)字串替換

在這里插入圖片描述

(1)替換所有的指定內容
在這里插入圖片描述

replaceAll 的使用

 public static void main(String[] args) {
        String str = "abcabcacbabc";
        System.out.println(str);
        System.out.println("=================");
        String ret = str.replaceAll("ab","AB");
        System.out.println(ret);
    }

運行結果:

在這里插入圖片描述


成功的把所有的 “ab” 替換成為 “AB”.


(2)替換首個要替換的內容.
在這里插入圖片描述

replaceFirst 的使用

 public static void main(String[] args) {
        String str = "abcabcacbabc";
        System.out.println(str);
        System.out.println("=================");
        String ret = str.replaceFirst("ab","AB");
        System.out.println(ret);
    }

運行結果:

在這里插入圖片描述

注意說明:

??由于字串是不可變物件, 替換不修改當前字串, 而是產生一個新的字串.


(4)字串拆分


??可以將一個完整的字串按照指定的分隔符劃分為若干個子字串,

在這里插入圖片描述

1.將字串全部拆分
在這里插入圖片描述


??接收的型別是字串陣列型別,傳引數時,傳一個我們想要分割的符號,


split 的使用

  public static void main(String[] args) {
        String str = "rain7 is cool";
        String[] strs = str.split(" ");
        for (String s:strs) {
            System.out.println(s);
        }
    }

??我們在用 split 方法時, 以 空格 為分割符,將我們的str 字串 進行拆分


我們來看拆分的效果

在這里插入圖片描述

2.帶兩個引數的split 方法
在這里插入圖片描述


還是以上面的字串為例

   public static void main(String[] args) {
        String str = "rain7 is cool";
        String[] strs = str.split(" ",2);
        for (String s:strs) {
            System.out.println(s);
        }
    }

運行結果:
在這里插入圖片描述

??我們除了將字串作為引數,還將limit 設定為2,那么拆分后的陣列長度就為2,所以運行結果就如上所示,


難點

??拆分是特別常用的操作. 一定要重點掌握. 另外有些特殊字符作為分割符可能無法正確切分, 需要加上轉義字符


示例1

拆分 IP 地址

比如說我們要分割IP 地址,192.168.1.1,以 “.” 分割,

當我們運行時會發現 列印為空,這是為什么呢?

有些符號比較特殊,必須用到轉義字符

“ \. ”才能表示一個真正的 “.” 

同時"\"也需要進行轉義,那么就又要再加一個斜杠,

“\\.”這時字串才只能被 “ . ”分割,
public static void main(String[] args) {
        String str = "192.168.1.1";
        String[] strs = str.split("\\.");
        for (String s:strs) {
            System.out.println(s);
        }
    }

運行結果

在這里插入圖片描述

1. 字符"|","*","+"都得加上轉義字符,前面加上"\\".
2. 而如果是"\",那么就得寫成"\\".
3. 如果一個字串中有多個分隔符,可以用"|"作為連字符.

連字符 “ | ” 的使用

 public static void main(String[] args) {
        String str = "1212@qq.com";
        String[] ret = str.split("@|\\.");
        for (String s:ret) {
            System.out.println(s);
        }
    }

運行結果:

在這里插入圖片描述


我們來一道練習題:

在這里插入圖片描述

代碼題解:

 public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNext()){
            String ret ="";
            String str = scanner.nextLine();
            String[] strs = str.split(" ");
            for (String s:strs) {
                ret += s;
            }

            System.out.println(ret);
        }
    }

運行結果:

在這里插入圖片描述

注意:

1.注意多組輸入
2.不建議在for回圈中拼接字串,在之后講到的StringBuilder StringBuffer 之后可以知道如何拼接,

(5)字串截取

從一個完整的字串之中截取出部分內容,可用方法如下:

在這里插入圖片描述

1.從指定下標截取到字串結束
在這里插入圖片描述

方法的使用

 public static void main(String[] args) {
        String str = "ilikeBeijing";
        String ret = str.substring(4);
        System.out.println(ret);
    }

運行結果:

在這里插入圖片描述

2.帶有兩個引數的subString 方法,截取指定下標范圍內的字串內容
在這里插入圖片描述

方法的使用

 public static void main(String[] args) {
        String str = "HelloWorld";
        String ret = str.substring(4,9);
        System.out.println(ret);
    }

運行結果

在這里插入圖片描述
注意:

1.指定下標范圍 是 左閉右開的區間

2.截取后的字串是一個新的物件

(6)其他操作方法

字串操作還有很多其他的方法,在這里我們只進行簡單介紹,

在這里插入圖片描述

(7)字串操作練習題


1.逆置字串


題目要求

將字串進行整體逆置


代碼題解:

   public static String reverse(String s){
        if(s==null){
            return null;
        }

        int begun = 0;
        int end = s.length()-1;
        char[] chars = s.toCharArray();
        while(begun<end){
            char tmp = chars[begun] ;
            chars [begun] = chars [end];
            chars[end] = tmp;
            begun++;
            end--;
        }
        return new String(chars);
    }


    public static void main(String[] args) {
        String str = "Hello World!";
        String ret = reverse(str);
        System.out.println(ret);
    }


運行結果:
在這里插入圖片描述


成功的將字串進行逆置


2.翻轉字串

在這里插入圖片描述


??我們首先對題目進行一下解讀,我們要實作一個方法,給這個方法傳入 一個字串和一個 整數 size ,將大小為 size 的左半區 翻轉到 右半區,如圖所示:


在這里插入圖片描述


思路實作:

1.首先將size 左半區進行單獨逆置,

2.再將 size的右半區單獨逆置,

3.整體字串進行逆置,

在這里插入圖片描述

代碼展示:

 public static String reverse(String s,int begun,int end){
        if(s==null){
            return null;
        }

        char[] chars = s.toCharArray();
        while(begun<end){
            char tmp = chars[begun] ;
            chars [begun] = chars [end];
            chars[end] = tmp;
            begun++;
            end--;
        }
        return new String(chars);
    }

    public static String reversSentence(String str,int k){
        str = reverse(str,0,k-1);
        str = reverse(str,k,str.length()-1);
        str = reverse(str,0,str.length()-1);

        return str;
    }

    public static void main(String[] args) {
       Scanner scanner = new Scanner(System.in);
       String str = scanner.next();
       int n = scanner.nextInt();
       String ret = reversSentence(str,n);
        System.out.println(ret);
    }

運行結果:

在這里插入圖片描述

八、StringBuffer 和 StringBuilder


??StringBuffer 和 StringBuilder 又是一種新的字串型別,

??通常來講String的操作比較簡單,但是由于String的不可更改特性,為了方便字串的修改,提供 StringBuffer 和 StringBuilder 類,

??StringBuffer 和 StringBuilder 在功能上大部分是相同的,在這里我們著重介紹 StringBuffer.


(1)append 方法


??在String中使用"+"來進行字串連接,但是這個操作在StringBuffer類中需要更改為append()方法,


??String和StringBuffer最大的區別在于:String的內容無法修改,而StringBuffer的內容可以修改,頻繁修改字串的情況考慮使用 StingBuffer,


 public static void main(String[] args) {
        StringBuffer sb = new StringBuffer();
        sb.append("a");
        sb.append("b");
        sb.append("c");
        System.out.println(sb);
    }

運行結果:

在這里插入圖片描述
我們來看一下 StringBuffer 的 append 方法的原始碼

在這里插入圖片描述
??最后回傳的是 this,在字串本身拼接字串,同時StringBuffer 有自己重寫的 toString 方法,可以直接進行列印,

我們來看一下 以下的代碼:

  public static void main(String[] args) {
       String str1 = "abc";
       String str2 = "def";
       String str3 = str1+str2;
       System.out.println(str3);

    }

我們對以上代碼進行編譯一下:

在這里插入圖片描述
在編譯的程序中,我們發現StringBuilder.append 方法的出現;


我們將這個程序用 StringBuilder 寫一下:

   public static void main(String[] args) {
        String str1 ="abc";
        String str2 = "def";
        StringBuilder sb = new StringBuilder();
        sb.append(str1);
        sb.append(str2);
        String str3 = sb.toString();
        System.out.println(str3);
    }

說明:

??String 的“+” 拼接,會被底層優化為一個 StringBuilder ,拼接的時候會用到 append 方法


(2)注意


注意:??String和StringBuffer類不能直接轉換,如果要想互相轉換,可以采用如下原則:

??String變為StringBuffer:利用StringBuffer的構造方法或append()方法
??StringBuffer變為String:呼叫toString()方法,

??除了append()方法外,StringBuffer也有一些String類沒有的方法:


字串反轉:

public synchronized StringBuffer reverse();

(3)區別


String 和 StringBuilder 及 StringBuffer 的區別

String 進行拼接時,底層會被優化為StringBuilder

String的拼接會產生臨時物件,但是后兩者每次都只是回傳當前物件的參考,

String的內容不可修改,StringBuffer與StringBuilder的內容可以修改.


StringBuilder 和 StringBuffer 的區別

我們來看一下這兩個類的 append 方法

在這里插入圖片描述


所以 StringBuffer 和 StringBuilder 的區別主要體現在執行緒安全上 ,


1.StringBuffer與StringBuilder大部分功能是相似的

2.StringBuffer采用同步處理,屬于執行緒安全操作;而StringBuilder未采用同步處理,屬于執行緒不安全操作


??字串操作是我們以后作業中非常常用的操作. 使用起來都非常簡單方便, 我們一定要使用熟練.


??好了今天的知識就分享到這里,希望大家多多練習,熟練掌握,感謝大家的欣賞與關注!!


謝謝欣賞!



Java基礎語法(十)——認識例外 已更新,希望大家多多關注哦!



完!

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/286281.html

標籤:java

上一篇:Java小專案另一個水果攤

下一篇:我丟,去面試初級Java開發崗位,被問到泛型?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more