JavaRush /Java Blog /Random-TW /Java 字串。面試問題與答案,第 2 部分
Andrey
等級 26

Java 字串。面試問題與答案,第 2 部分

在 Random-TW 群組發布
不幸的是,這篇文章無法用一個片段來表達;我不得不將其分成兩部分。 請參閱這裡的開頭 Java 字串。 面試問題和答案,第 2 - 1 部分

12. 寫一個函數來找出給定字串中最長的回文

字串可以包含回文字串,找到最長的回文字串是一個程式設計問題。這裡的關鍵點是,從任何回文的中間開始,如果我們向右和向左移動 1 個字符,它總是相同的字符。例如,12321,中間是3,如果我們從目前位置繼續向兩個方向移動,我們將得到2,然後得到1。我們在Java程式中使用類似的邏輯來找到最長的回文。但是,如果回文長度是偶數,那麼中間的長度也是偶數,所以我們需要確保我們的程式中也提供了這個,例如12333321,中間是33,如果我們繼續移動在兩個方向上,我們都會得到3 、2 和1。在我們的程式中,我們首先檢查結果字串,並檢查左右字元。我們還有兩個全域變數來儲存回文的初始位置。我們還需要檢查是否已經找到更長的回文,因為我們可以在給定字串中找到多個回文。下面是一個在所有情況下都能正常工作的範例程式。我們可以透過將 while 循環移至單獨的方法中來改進上述程式碼,但我會將這部分留給您。如果您有更好的實作或程式以某種方式失敗,請告訴我。
package com.journaldev.util;

public class LongestPalindromeFinder {

    public static void main(String[] args) {
        System.out.println(longestPalindromeString("1234"));
        System.out.println(longestPalindromeString("12321"));
        System.out.println(longestPalindromeString("9912321456"));
        System.out.println(longestPalindromeString("9912333321456"));
        System.out.println(longestPalindromeString("12145445499"));
    }

    public static String longestPalindromeString(String in) {
        char[] input = in.toCharArray();
        int longestPalindromeStart = 0;
        int longestPalindromeEnd = 0;

        for (int mid = 0; mid < input.length; mid++) {
            // для случая нечетного палиндрома How 12321, 3 будет серединой
            int left = mid-1;
            int right = mid+1;
            // нам необходимо двигаться влево и вправо на 1 позицию до конца
            while (left >= 0 && right < input.length) {
                // ниже проверка, является ли это палиндромом
                if (input[left] == input[right]) {
                    // обновление глобальных позиций, только если палиндром длиннее имеющегося
                    if (right - left > longestPalindromeEnd
                            - longestPalindromeStart) {
                        longestPalindromeStart = left;
                        longestPalindromeEnd = right;
                    }
                }
                left--;
                right++;
            }
            // для четного палиндрома у нас должна быть подобная логика с размером середины 2
            // для этого мы начнем на одну позицию правее
            left = mid-1;
            right = mid + 2;// к примеру, для 12333321 мы выбрали 33 в качестве середины
            while (left >= 0 && right < input.length)
            {
                if (input[left] == input[right]) {
                    if (right - left > longestPalindromeEnd
                            - longestPalindromeStart) {
                        longestPalindromeStart = left;
                        longestPalindromeEnd = right;
                    }
                }
                left--;
                right++;
            }
        }
        // теперь у нас есть позиции для самого длинного палиндрома
        return in.substring(longestPalindromeStart, longestPalindromeEnd + 1);
    }
}
該程式將輸出以下內容:
1
12321
12321
12333321
454454

13. String、StringBuffer和StringBuilder有什麼差別

在 Java 中,字串是不可變的和最終確定的,因此我們所有的字串操作總是會建立一個新字串。字串操作是資源密集型的,因此 Java 提供了兩個有用的字串操作類別 -StringBufferStringBuilderStringBuffer並且StringBuilder是可變類別。操作StringBuffer是線程安全且同步的,但方法StringBuilder不是線程安全的。因此,當多個執行緒處理同一個字串StringBuffer時,我們應該使用StringBuilder. 因為它沒有同步的負擔, StringBuilder所以效率更高。StringBuffer

14.為什麼Java中字串是不可變的和最終確定的?

字串不變性有幾個優點:
  1. 字串池之所以可能,是因為字串在Java中是不可變的,因此虛擬機器節省了大量的堆疊空間,因為不同的字串變數指向池中的同一個變數。如果字串不是不可變的,則字串駐留是不可能的,因為如果任何變數更改其值,引用該字串的其他變數也會受到影響。

  2. 如果字串是可變的,那麼它就會成為應用程式的嚴重安全風險。例如,資料庫使用者名稱和密碼作為字串傳遞以獲得與資料庫的連接,而在套接字編程中,主機和連接埠詳細資訊作為字串傳遞。由於該字串是不可變的,因此其值無法更改,否則任何駭客都可以更改連結的值並導致應用程式的安全性出現問題。

  3. 由於字串是不可變的,因此它是線程安全的,並且可以在不同線程之間共享字串的一個實例。這避免了線程安全的同步,字串是完全線程安全的。

  4. Java 中使用字串classloader,不變性確保使用Classloader. 例如,當您嘗試載入java.sql.Connection一個類別時,請考慮一個類別實例,但引用值會變更為myhacked.Connection可能對資料庫執行不需要的操作的類別。

  5. 由於字串是不可變的,因此hashcode在創建時就被快取起來,不需要再次計算。這使得該字串成為鍵入的絕佳候選者Map,並且其處理速度將比其他鍵更快HashMap。這就是為什麼 string 是最常用的用作鍵的物件的原因HashMap

15. 如何將字串分割成多個部分?

我們可以使用一種方法,split(String regex)使用正規表示式作為分隔符號將字串拆分為字串數組。
import java.util.Arrays;

public class JavaSplitString {
    public static void main(String[] args) {
        String line = "I am a java developer";
        String[] words = line.split(" ");
        String[] twoWords = line.split(" ", 2);
        System.out.println("String split with delimiter: "+Arrays.toString(words));
        System.out.println("String split into two: "+Arrays.toString(twoWords));
        //split string delimited with special characters
        String wordsWithNumbers = "I|am|a|java|developer";
        String[] numbers = wordsWithNumbers.split("\\|");
        System.out.println("String split with special character: "+Arrays.toString(numbers));
    }
}
該方法split(String regex, int numOfStrings)是一個重載方法,用於將字串拆分為指定行數。我們可以使用反斜線將正規表示式特殊字元用作正規字元。該程式將輸出以下內容:
String split with delimiter: [I, am, a, java, developer]
String split into two: [I, am a java developer]
String split with special character: [I, am, a, java, developer]

16. 為什麼字串陣列比字串更適合儲存密碼?

Java 中的字串是不可變的,儲存在字串池中。一旦它被創建,它就會保留在池中直到被垃圾收集,所以當我們認為我們已經完成了密碼時,它會在記憶體中保留一段時間,並且沒有辦法避免這種情況。這是一個安全風險,因為任何有權存取記憶體轉儲的人都能夠找到明文形式的密碼。如果我們使用字元數組來儲存密碼,我們可以在使用完畢後將其清除。這樣我們就可以控制它在記憶體中保留的時間,避免字串固有的安全風險。

17. 在Java中如何檢查兩個字串的相似性?

有兩種方法可以檢查兩個字串是否相等 - 使用“ ==”運算符,或使用equals. 當我們使用「==」運算子時,它會檢查字串的值作為引用,但在程式設計中大多數時候我們只檢查該值的字串等效性。因此,我們必須使用 equals 方法來測試兩個字串是否相等。我們還有一種方法equalsIgnoreCase可以用來忽略大小寫。
String s1 = "abc";
String s2 = "abc";
String s3= new String("abc");
System.out.println("s1 == s2 ? "+(s1==s2)); //true
System.out.println("s1 == s3 ? "+(s1==s3)); //false
System.out.println("s1 equals s3 ? "+(s1.equals(s3))); //true

18.什麼是字串池?

顧名思義,字串池是儲存在 Java 堆中的字串的集合。我們知道String這是Java中的一個特殊類,我們可以使用new運算子來建立該類別的對象,就像我們可以透過在雙引號中提供字串值來建立物件一樣。下圖解釋了字串池是如何在Java堆中分配的,以及當我們使用不同的方式建立字串時會發生什麼。 Java 字串。 面試問題和答案,第 2 - 2 部分字串池之所以成為可能,只是因為Java的字串不變性和字串駐留思想的實作。字串池也是享元模式的範例。字串池有助於節省大量內存,但另一方面,創建行需要更多時間。當我們使用雙引號創建字串時,它首先在池中查找具有相同值的字串,如果找到則簡單地返回引用,否則在池中創建一個新字串然後返回引用。然而,當我們使用new運算符時,我們強制類別String創建一個新的字串對象,然後我們可以使用該方法intern()將字串放入池中,或者從池中獲取對另一個String具有相同值的對象的引用。下面的範例顯示了字串池的工作原理。
public class StringPool {
    public static void main(String[] args) {
        String s1 = "Cat";
        String s2 = "Cat";
        String s3 = new String("Cat");

        System.out.println("s1 == s2 :"+(s1==s2));
        System.out.println("s1 == s3 :"+(s1==s3));
    }
}
該程式將輸出以下內容:
s1 == s2 :true
s1 == s3 :false

19. intern()方法的作用是什麼?

當呼叫該方法時intern(),如果字串池已經包含與我們的物件等效的字串(經該方法驗證equals(Object)),則傳回對池中字串的參考。否則,字串物件將被加入到池中,並傳回對該物件的參考。此方法始終傳回與目前字串具有相同值的字串,但保證它將是唯一字串池中的字串。以下是該方法如何運作的範例intern()
public class StringPool {
    public static void main(String[] args) {
        String a = "string a";
        String b = new String("string a");
        String c = b.intern();

        System.out.println(a == b);
        System.out.println(b == c);
        System.out.println(a == c);
    }
}
Программа выведет следующее:false
false
true

20. Java中字串是執行緒安全的嗎?

字串是不可變的,因此我們無法在程式中更改它們的值。因此它們是線程安全的,可以安全地在多線程環境中使用。

21.為什麼String是Java中HashMap中流行的鍵?

由於字串是不可變的,因此它們的雜湊碼在創建時會被緩存,不需要重新計算。這使得字串成為鍵的絕佳候選者Map,並且它們的處理速度比其他鍵物件更快HashMap。這就是為什麼字串主要用作鍵的原因HashMap。我希望本文列出的問題對您的面試有所幫助,如果我遺漏了什麼,請告訴我。 原文連結 作者:Pankaj Kumar
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION