JavaRush /จาวาบล็อก /Random-TH /สตริงจาวา คำถามและคำตอบในการสัมภาษณ์ ตอนที่ 2
Andrey
ระดับ

สตริงจาวา คำถามและคำตอบในการสัมภาษณ์ ตอนที่ 2

เผยแพร่ในกลุ่ม
น่าเสียดายที่บทความนี้ไม่พอดีในส่วนเดียว ฉันต้องแบ่งออกเป็นสองส่วน ดูจุดเริ่มต้นได้ที่นี่ สตริงจาวา  คำถามและคำตอบในการสัมภาษณ์ ตอนที่ 2 - 1

12. เขียนฟังก์ชันเพื่อค้นหาพาลินโดรมที่ยาวที่สุดในสตริงที่กำหนด

สตริงสามารถมีสตริงพาลินโดรมได้ และการค้นหาพาลินโดรมที่ยาวที่สุดนั้นเป็นเรื่องของการเขียนโปรแกรม ประเด็นสำคัญคือจากตรงกลางของพาลินโดรมใดๆ ถ้าเราไปทางขวาและซ้ายทีละ 1 อักขระ มันก็จะเป็นอักขระเดียวกันเสมอ ตัวอย่างเช่น 12321 ตรงกลางคือ 3 และถ้าเราเคลื่อนจากตำแหน่งปัจจุบันในทั้งสองทิศทาง เราจะได้ 2 และ 1 เราใช้ตรรกะที่คล้ายกันในโปรแกรม Java ของเราเพื่อค้นหาพาลินโดรมที่ยาวที่สุด อย่างไรก็ตาม ถ้าความยาวของพาลินโดรมเป็นเลขคู่ ความยาวของเส้นตรงกลางก็จะเป็นเลขคู่ด้วย ดังนั้น เราจึงต้องแน่ใจว่าค่านี้ระบุไว้ในโปรแกรมของเราด้วย เช่น 12333321 ค่าตรงกลางคือ 33 และถ้าเราเคลื่อนที่ต่อไป ในทั้งสองทิศทางเราจะได้ 3, 2 และ 1 ในโปรแกรมของเรา เราต้องผ่านสตริงผลลัพธ์โดยให้ตรงกลางเป็นอันดับแรก และตรวจสอบอักขระด้านซ้ายและขวา นอกจากนี้เรายังมีตัวแปรร่วมสองตัวสำหรับจัดเก็บตำแหน่งเริ่มต้นของพาลินโดรม เรายังจำเป็นต้องตรวจสอบด้วยว่าพบพาลินโดรมที่ยาวกว่านั้นแล้วหรือไม่ เนื่องจากเราสามารถค้นหาพาลินโดรมหลายอันในสตริงที่กำหนด ด้านล่างนี้คือตัวอย่างโปรแกรมที่ทำงานได้ดีในทุกกรณี เราสามารถปรับปรุงโค้ดด้านบนได้โดยการย้าย while loop ไปยังวิธีอื่น แต่ฉันจะทิ้งส่วนนั้นไว้ให้คุณ โปรดแจ้งให้เราทราบหากคุณมีการใช้งานที่ดีขึ้นหรือหากโปรแกรมล้มเหลวในทางใดทางหนึ่ง
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 จึงจัดเตรียมคลาสที่มีประโยชน์สองคลาสสำหรับการจัดการสตริง - StringBufferและStringBuilder. StringBufferและ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. เมื่อเราใช้==โอเปอเรเตอร์ “ ” มันจะตรวจสอบค่าของสตริงเป็นข้อมูลอ้างอิง แต่ในการเขียนโปรแกรมส่วนใหญ่เราจะตรวจสอบความเทียบเท่าของสตริงสำหรับค่าเท่านั้น ดังนั้นเราจึงต้องใช้วิธีเท่ากับเพื่อทดสอบสองสตริงเพื่อความเท่าเทียมกัน นอกจากนี้ยังมีวิธี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. สตริงพูลคืออะไร?

ตามชื่อที่แนะนำ string pool คือชุดของสตริงที่เก็บอยู่ในฮีป Java เรารู้ว่าStringนี่คือคลาสพิเศษใน Java และเราสามารถสร้างอ็อบเจ็กต์ของคลาสนี้โดยใช้ตัวดำเนินการใหม่ เช่นเดียวกับที่เราสามารถสร้างอ็อบเจ็กต์โดยระบุค่าของสตริงในเครื่องหมายคำพูดคู่ แผนภาพด้านล่างอธิบายวิธีการจัดสรรสตริงพูลในฮีป Java และสิ่งที่เกิดขึ้นเมื่อเราใช้วิธีต่างๆ ในการสร้างสตริง สตริงจาวา  คำถามและคำตอบในการสัมภาษณ์ ตอนที่ 2 - 2การรวมสตริงเป็นไปได้เพียงเพราะความไม่เปลี่ยนรูปของสตริงของ Java และการนำแนวคิดของการฝึกงานสตริงไปใช้ สตริงพูลก็เป็นตัวอย่างของรูปแบบฟลายเวทเช่นกัน String Pool ช่วยประหยัดหน่วยความจำได้มาก แต่ในทางกลับกัน การสร้างแถวต้องใช้เวลามากกว่า เมื่อเราใช้เครื่องหมายคำพูดคู่เพื่อสร้างสตริง อันดับแรกจะค้นหาสตริงในพูลที่มีค่าเดียวกัน หากพบก็เพียงส่งคืนการอ้างอิง ไม่เช่นนั้นสตริงใหม่จะถูกสร้างขึ้นในพูลแล้วส่งคืนการอ้างอิง อย่างไรก็ตาม เมื่อเราใช้ตัวดำเนินการใหม่ เราจะบังคับให้คลาส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()หากพูลสตริงมีสตริงที่เทียบเท่ากับอ็อบเจ็กต์ของเราอยู่แล้ว ตามที่ตรวจสอบโดยเมธอด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 จึงเป็นคีย์ยอดนิยมใน HashMap ใน Java

เนื่องจากสตริงไม่เปลี่ยนรูป รหัสแฮชของสตริงจึงถูกแคชในขณะที่สร้าง และไม่จำเป็นต้องคำนวณใหม่ ซึ่งทำให้สตริงเป็นตัวเลือกที่ดีเยี่ยมสำหรับคีย์Mapและจะมีการประมวลผลได้เร็วกว่าออบเจ็กต์คีย์อื่นๆ HashMapนี่คือเหตุผลว่าทำไมสตริงจึงถูกใช้เป็นคีย์เป็นส่วนHashMapใหญ่ ฉันหวังว่าคำถามในบทความนี้จะช่วยคุณในการสัมภาษณ์ โปรดแจ้งให้เราทราบหากพลาดอะไรไป ลิงก์ไปยังบทความต้นฉบับ ผู้แต่ง: Pankaj Kumar
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION