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 מספקת שתי מחלקות שימושיות למניפולציה של מחרוזות -StringBuffer
ו StringBuilder
. StringBuffer
והם StringBuilder
מחלקות הניתנות לשינוי. פעולות עם StringBuffer
בטוחות בשרשור ומסונכרנות, אבל השיטות StringBuilder
אינן בטוחות בשרשור. אז כאשר שרשורים מרובים עובדים על אותה מחרוזת אנחנו צריכים להשתמש StringBuffer
, אבל בסביבה עם שרשור בודד אנחנו צריכים להשתמש StringBuilder
. StringBuilder
פרודוקטיבי יותר מאשר StringBuffer
בגלל שהוא לא עמוס בסנכרון.
14. מדוע מחרוזת ניתנת לשינוי וסופית בג'אווה?
ישנם מספר יתרונות לבלתי משתנה של מחרוזת:-
איגום מחרוזות אפשרי רק בגלל שהמחרוזת אינה ניתנת לשינוי ב-Java, ולכן המכונה הוירטואלית חוסכת הרבה שטח ערימה שכן משתני מחרוזת שונים מצביעים על אותו משתנה במאגר. אם מחרוזת לא הייתה ניתנת לשינוי, אזי התמחות מחרוזת לא הייתה אפשרית, מכיוון שאם משתנה כלשהו משנה את ערכו, משתנים אחרים המתייחסים למחרוזת זו יושפעו גם הם.
-
אם המחרוזת ניתנת לשינוי, היא הופכת לסיכון אבטחה רציני עבור היישום. לדוגמה, שם המשתמש והסיסמה של מסד הנתונים מועברים כמחרוזת כדי להשיג חיבור למסד הנתונים ובתכנות socket פרטי המארח והיציאה מועברים כמחרוזת. מכיוון שהמחרוזת אינה ניתנת לשינוי, לא ניתן לשנות את הערך שלה, אחרת כל האקר יכול לשנות את ערך הקישור ולגרום לבעיות באבטחת האפליקציה.
-
מכיוון שהמחרוזת אינה ניתנת לשינוי, היא בטוחה לחוטים וניתן לשתף מופע אחד של המחרוזת בין חוטים שונים. זה ימנע סנכרון לבטיחות חוטים, מיתרים בטוחים לחלוטין.
-
משתמשים במחרוזות ב-Java
classloader
והאי-שינוי מבטיח שהמחלקה נטענת בצורה נכונה באמצעותClassloader
. לדוגמה, חשבו על מופע מחלקה כאשר אתם מנסים לטעוןjava.sql.Connection
מחלקה, אך ערך ההפניה משתנה למחלקהmyhacked.Connection
שעלולה לעשות דברים לא רצויים למסד הנתונים שלכם. -
מכיוון שהמחרוזת אינה ניתנת לשינוי, היא
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 והיא מאוחסנת במאגר מחרוזות. ברגע שהוא נוצר, הוא נשאר בבריכה עד שהוא נאסף, כך שכאשר אנו חושבים שסיימנו עם הסיסמה, הוא נשאר זמין בזיכרון לזמן מה ואין דרך להימנע מכך. זהו סיכון אבטחה מכיוון שכל מי שיש לו גישה ל-dump הזיכרון יוכל למצוא את הסיסמה בטקסט ברור. אם נשתמש במערך תווים לאחסון הסיסמה, נוכל לנקות אותה לאחר שנסיים איתה. כך נוכל לשלוט כמה זמן הוא נשאר בזיכרון, ולמנוע את סיכוני האבטחה הגלומים במחרוזת.17. איך בודקים שתי מחרוזות לדמיון בג'אווה?
ישנן שתי דרכים לבדוק אם שתי מחרוזות שוות ערך - שימוש==
באופרטור " " או שימוש ב- 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 ומה קורה כאשר אנו משתמשים בדרכים שונות ליצירת מחרוזות. איגום מחרוזות אפשרי אך ורק בגלל חוסר השינוי של מחרוזות של Java ויישום הרעיון של התמחות מחרוזת. בריכת מיתרים היא גם דוגמה לתבנית Flyweight. מאגר מיתרים עוזר לחסוך הרבה זיכרון, אבל מצד שני, יצירת שורה לוקחת יותר זמן. כאשר אנו משתמשים במירכאות כפולות ליצירת מחרוזת, היא תחילה מחפשת מחרוזת במאגר עם אותו ערך, אם היא נמצאת אז פשוט מחזירה הפניה, אחרת נוצרת מחרוזת חדשה במאגר ולאחר מכן מחזירה הפניה. עם זאת, כאשר אנו משתמשים באופרטור החדש, אנו מכריחים את המחלקה 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 הוא מפתח פופולרי ב-HashMap ב-Java?
מכיוון שהמחרוזות אינן ניתנות לשינוי, קוד ה-hash שלהן נשמר במטמון בזמן היצירה ואינו דורש חישוב מחדש. זה הופך מחרוזות למועמד מצוין למפתחMap
והן מעובדות מהר יותר מאובייקטי מפתח אחרים HashMap
. זו הסיבה שהמחרוזות משמשות בעיקר כמפתחות HashMap
. אני מקווה שהשאלות המפורטות במאמר זה יעזרו לך בראיונות שלך, אנא הודע לי אם פספסתי משהו. קישור למאמר המקורי מחבר: Pankaj Kumar
GO TO FULL VERSION