JavaRush /Java Blog /Random-JA /Java 文字列。インタビューの質問と回答、パート 2
Andrey
レベル 26

Java 文字列。インタビューの質問と回答、パート 2

Random-JA グループに公開済み
残念ながら、この記事は 1 つの断片に収まらず、2 つの部分に分割する必要がありました。 冒頭はこちらからご覧ください Java 文字列。 インタビューの質問と回答、パート 2 - 1

12. 指定された文字列内の最長の回文を見つける関数を作成します。

文字列には回文文字列を含めることができ、最長の回文を見つけるのはプログラミングの問題です。ここで重要な点は、回文の中央から 1 文字ずつ右に行っても左に行っても、それは常に同じ文字になるということです。たとえば、12321 の場合、中央は 3 で、現在の位置から両方向に移動し続けると、2 が得られ、次に 1 が得られます。Java プログラムでも同様のロジックを使用して、最長の回文を見つけます。ただし、回文の長さが偶数であれば、中央の長さも偶数であるため、これもプログラムで提供されていることを確認する必要があります。たとえば、12333321、中央は 33 で、移動を続けると、両方向とも、3、2、1 が得られます。プログラムでは、最初に中央を先頭にして結果の文字列を調べ、左右の文字をチェックします。また、回文の初期位置を保存する 2 つのグローバル変数もあります。また、指定された文字列内で複数の回文が見つかる可能性があるため、さらに長い回文がすでに見つかっているかどうかを確認する必要があります。以下は、どのような場合でも正常に動作するプログラム例です。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 では文字列操作に役立つ 2 つのクラス (StringBufferと )が提供されていますStringBuilderStringBufferStringBuilder可変クラスです。の操作はStringBufferスレッド セーフで同期されていますが、メソッドはStringBuilderスレッド セーフではありません。したがって、複数のスレッドが同じ文字列を処理している場合は を使用する必要がありますStringBufferが、単一スレッド環境では を使用する必要がありますStringBuilder。 同期の負担がないため、 StringBuilder生産性が向上します。StringBuffer

14. Java では文字列が不変でファイナライズされるのはなぜですか?

文字列の不変性にはいくつかの利点があります。
  1. 文字列プールは、Java では文字列が不変であるためにのみ可能です。したがって、異なる文字列変数がプール内の同じ変数を指すため、仮想マシンは大量のヒープ領域を節約します。文字列が不変でない場合、変数の値が変更されると、その文字列を参照する他の変数も影響を受けるため、文字列インターニングは不可能になります。

  2. 文字列が変更可能な場合、アプリケーションにとって重大なセキュリティ リスクになります。たとえば、データベースへの接続を取得するためにデータベースのユーザー名とパスワードが文字列として渡され、ソケット プログラミングではホストとポートの詳細が文字列として渡されます。文字列は不変であるため、その値を変更することはできません。そうしないと、ハッカーがリンクの値を変更し、アプリケーションのセキュリティに問題を引き起こす可能性があります。

  3. 文字列は不変であるため、スレッドセーフであり、文字列の 1 つのインスタンスを異なるスレッド間で共有できます。これにより、スレッド セーフのための同期が回避され、文字列は完全にスレッド セーフになります。

  4. 文字列は Java で使用されclassloader、不変性により、クラスが を使用して正しくロードされることが保証されますClassloader。たとえば、java.sql.Connectionクラスをロードしようとしたときに、参照値がmyhacked.Connectionデータベースに対して望ましくないことを行う可能性のあるクラスに変更された場合のクラス インスタンスについて考えてみましょう。

  5. 文字列は不変であるため、hashcode作成時にキャッシュされ、再度計算する必要はありません。これにより、その文字列はキー入力の優れた候補となりMap、その処理は他のキーよりも高速になりますHashMap。これが、文字列がキーとして使用される最も一般的に使用されるオブジェクトである理由です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 で 2 つの文字列の類似性をどのようにチェックしますか?

2 つの文字列が同等かどうかを確認するには、「==」演算子を使用する方法とequals. 「 」演算子を使用すると==、文字列の値が参照としてチェックされますが、プログラミングではほとんどの場合、値の文字列の等価性をチェックします。したがって、equals メソッドを使用して 2 つの文字列が等しいかどうかをテストする必要があります。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 ヒープに格納される文字列のコレクションです。これは Java の特別なクラスであることがわかっておりString、文字列の値を二重引用符で囲んでオブジェクトを作成するのと同じように、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. Java の HashMap で String が人気のキーなのはなぜですか?

文字列は不変であるため、そのハッシュ コードは作成時にキャッシュされ、再計算する必要はありません。これにより、文字列はキーの優れた候補となりMap、他のキー オブジェクトよりも高速に処理されますHashMap。これが、文字列がキーとして主に使用される理由ですHashMap。この記事に記載されている質問が面接で役立つことを願っています。何か見逃した場合はお知らせください。 元記事へのリンク 著者: Pankaj Kumar
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION