JavaRush /Blog Java /Random-PL /Ciąg Java. Pytania i odpowiedzi na rozmowie kwalifikacyjn...
Andrey
Poziom 26

Ciąg Java. Pytania i odpowiedzi na rozmowie kwalifikacyjnej, część 2

Opublikowano w grupie Random-PL
Niestety artykuł nie zmieścił się w jednym fragmencie, musiałem go podzielić na dwie części. Zobacz początek tutaj Ciąg Java.  Pytania i odpowiedzi na rozmowie kwalifikacyjnej, część 2 - 1

12. Napisz funkcję znajdującą najdłuższy palindrom w podanym ciągu znaków

Ciąg może zawierać ciągi palindromowe, a znalezienie najdłuższego palindromu jest kwestią programowania. Kluczową kwestią jest to, że jeśli od środka dowolnego palindromu przejdziemy w prawo i w lewo o 1 znak, zawsze będzie to ten sam znak. Na przykład 12321, środek to 3 i jeśli będziemy kontynuować przesuwanie się od bieżącej pozycji w obu kierunkach, otrzymamy 2, a następnie 1. Używamy podobnej logiki w naszym programie Java, aby znaleźć najdłuższy palindrom. Jeśli jednak długość palindromu jest parzysta, długość środka również jest parzysta, więc musimy się upewnić, że jest to również uwzględnione w naszym programie, np. 12333321, środek wynosi 33 i jeśli będziemy kontynuować ruch w obu kierunkach otrzymamy 3, 2 i 1. W naszym programie przechodzimy przez wynikowy ciąg ze środkiem w pierwszej kolejności i sprawdzamy lewy i prawy znak. Mamy również dwie zmienne globalne do przechowywania początkowej pozycji palindromu. Musimy także sprawdzić, czy nie znaleziono już dłuższego palindromu, ponieważ w danym ciągu możemy znaleźć wiele palindromów. Poniżej znajduje się przykładowy program, który działa dobrze we wszystkich przypadkach. Możemy ulepszyć powyższy kod, przenosząc pętlę while do osobnej metody, ale tę część pozostawię Tobie. Proszę dać mi znać, jeśli masz lepszą implementację lub jeśli program zawodzi w jakiś sposób.
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++) {
            // для случая нечетного палиндрома Jak 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);
    }
}
Program wyświetli następujące informacje:
1
12321
12321
12333321
454454

13. Jakie są różnice pomiędzy String, StringBuffer i StringBuilder

Ciąg jest niezmienny i sfinalizowany w Javie, więc wszystkie nasze manipulacje ciągami zawsze spowodują utworzenie nowego ciągu. Manipulowanie ciągami wymaga dużych zasobów, dlatego Java udostępnia dwie przydatne klasy do manipulacji ciągami — StringBufferi StringBuilder. StringBufferi StringBuildersą klasami modyfikowalnymi. Operacje za pomocą StringBuffersą bezpieczne dla wątków i zsynchronizowane, ale metody StringBuildernie są bezpieczne dla wątków. Zatem gdy wiele wątków pracuje na tym samym ciągu znaków, powinniśmy użyć StringBuffer, ale w środowisku jednowątkowym powinniśmy użyć StringBuilder. StringBuilderbardziej produktywny niż StringBufferdlatego, że nie jest obciążony synchronizacją.

14. Dlaczego ciąg znaków jest niezmienny i sfinalizowany w Javie?

Niezmienność ciągów ma kilka zalet:
  1. Łączenie ciągów jest możliwe tylko dlatego, że ciąg jest niezmienny w Javie, dlatego maszyna wirtualna oszczędza dużo miejsca na stercie, ponieważ różne zmienne łańcuchowe wskazują na tę samą zmienną w puli. Jeśli ciąg znaków nie byłby niezmienny, wówczas internowanie ciągów nie byłoby możliwe, ponieważ jeśli jakakolwiek zmienna zmieni swoją wartość, będzie to miało wpływ również na inne zmienne odwołujące się do tego ciągu.

  2. Jeśli ciąg znaków można modyfikować, stanowi to poważne zagrożenie bezpieczeństwa aplikacji. Na przykład nazwa użytkownika i hasło bazy danych są przekazywane jako ciąg znaków w celu uzyskania połączenia z bazą danych, a podczas programowania gniazd szczegóły hosta i portu są przekazywane jako ciąg znaków. Ponieważ ciąg znaków jest niezmienny, nie można zmienić jego wartości, w przeciwnym razie każdy haker może zmienić wartość łącza i spowodować problemy z bezpieczeństwem aplikacji.

  3. Ponieważ ciąg jest niezmienny, jest bezpieczny dla wątków i jedno wystąpienie ciągu może być współużytkowane przez różne wątki. Pozwala to uniknąć synchronizacji dla bezpieczeństwa wątków, ciągi znaków są całkowicie bezpieczne dla wątków.

  4. W Javie używane są ciągi znaków, classloadera niezmienność gwarantuje, że klasa zostanie poprawnie załadowana przy użyciu Classloader. Weźmy na przykład instancję klasy, gdy próbujesz załadować java.sql.Connectionklasę, ale wartość referencyjna zostaje zmieniona na myhacked.Connectionklasę, która może zrobić niepożądane rzeczy z twoją bazą danych.

  5. Ponieważ ciąg znaków jest niezmienny, hashcodejest on buforowany w momencie tworzenia i nie ma potrzeby ponownego obliczania go. To sprawia, że ​​ciąg znaków jest doskonałym kandydatem na klucz, Mapa jego przetwarzanie będzie szybsze niż w przypadku innych kluczy HashMap. To jest powód, dla którego string jest najczęściej używanym obiektem używanym jako klucz HashMap.

15. Jak podzielić ciąg na części?

Możemy użyć metody split(String regex)podziału ciągu na tablicę ciągów, używając wyrażenia regularnego jako ogranicznika.
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));
    }
}
Metoda split(String regex, int numOfStrings)jest przeciążoną metodą dzielenia ciągu na określoną liczbę wierszy. Możemy użyć ukośnika odwrotnego, aby używać znaków specjalnych wyrażeń regularnych jako znaków zwykłych. Program wyświetli następujące informacje:
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. Dlaczego do przechowywania hasła lepsza jest tablica ciągów niż ciąg znaków?

Ciąg znaków jest niezmienny w Javie i jest przechowywany w puli ciągów. Raz utworzone pozostaje w puli aż do momentu wyrzucenia go do śmieci, więc gdy uznamy, że już z hasłem skończyliśmy, pozostaje ono przez jakiś czas dostępne w pamięci i nie da się tego uniknąć. Stanowi to zagrożenie bezpieczeństwa, ponieważ każdy, kto ma dostęp do zrzutu pamięci, będzie mógł znaleźć hasło w postaci zwykłego tekstu. Jeśli do przechowywania hasła użyjemy tablicy znaków, możemy je wyczyścić po zakończeniu. W ten sposób możemy kontrolować, jak długo pozostaje on w pamięci, unikając zagrożeń bezpieczeństwa związanych z ciągiem znaków.

17. Jak sprawdzić podobieństwo dwóch ciągów w Javie?

Istnieją dwa sposoby sprawdzenia, czy dwa ciągi znaków są równoważne — używając ==operatora „ ” lub używając operatora equals. Kiedy używamy ==operatora „ ”, sprawdza on wartość ciągu jako odniesienie, ale w programowaniu przez większość czasu sprawdzamy równoważność ciągu tylko pod względem wartości. Dlatego musimy użyć metody równości, aby przetestować dwa ciągi pod kątem równości. Istnieje również metoda, equalsIgnoreCasektórej możemy użyć do ignorowania wielkości liter.
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. Co to jest pula ciągów?

Jak sama nazwa wskazuje, pula ciągów to zbiór ciągów przechowywanych na stercie Java. Wiemy, że Stringjest to specjalna klasa w Javie i możemy tworzyć obiekty tej klasy za pomocą operatora new, tak samo jak możemy tworzyć obiekty, podając wartość ciągu znaków w cudzysłowie. Poniższy diagram wyjaśnia, w jaki sposób pula ciągów jest alokowana na stercie Java i co się dzieje, gdy używamy różnych sposobów tworzenia ciągów. Ciąg Java.  Pytania i odpowiedzi na rozmowie kwalifikacyjnej, część 2 - 2Pulowanie ciągów jest możliwe wyłącznie dzięki niezmienności ciągów w Javie i realizacji idei internowania ciągów. Pula strun jest również przykładem wzorca wagi muszej. Pula ciągów pomaga zaoszczędzić dużo pamięci, ale z drugiej strony utworzenie wiersza zajmuje więcej czasu. Kiedy używamy podwójnych cudzysłowów do utworzenia ciągu, najpierw szuka w puli ciągu o tej samej wartości, a jeśli zostanie znaleziony, po prostu zwraca referencję. W przeciwnym razie w puli tworzony jest nowy ciąg, a następnie zwraca referencję. Jednakże, gdy używamy operatora new, zmuszamy klasę Stringdo utworzenia nowego obiektu typu string, a następnie możemy użyć tej metody intern()do umieszczenia ciągu znaków w puli lub uzyskania referencji z puli do innego obiektu Stringo tej samej wartości. Poniżej znajduje się przykład pokazujący, jak działa pula ciągów.
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));
    }
}
Program wyświetli następujące informacje:
s1 == s2 :true
s1 == s3 :false

19. Do czego służy metoda intern()?

Po wywołaniu metody intern(), jeśli w puli ciągów znajduje się już ciąg znaków odpowiadający naszemu obiektowi, co zostało zweryfikowane metodą equals(Object), zwracane jest odwołanie do ciągu znaków z puli. W przeciwnym razie obiekt typu string jest dodawany do puli i zwracane jest odwołanie do tego obiektu. Ta metoda zawsze zwraca ciąg znaków, który ma taką samą wartość jak bieżący ciąg, ale gwarantuje, że będzie to ciąg z puli unikalnych ciągów. Poniżej znajduje się przykład działania metody 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. Czy ciągi znaków są bezpieczne w Javie?

Stringi są niezmienne, więc nie możemy zmienić ich wartości w programie. Dlatego są bezpieczne dla wątków i można ich bezpiecznie używać w środowisku wielowątkowym.

21. Dlaczego String jest popularnym kluczem w HashMap w Javie?

Ponieważ ciągi znaków są niezmienne, ich kod skrótu jest buforowany w momencie tworzenia i nie wymaga ponownego obliczania. To sprawia, że ​​ciągi znaków są doskonałym kandydatem na klucz Mapi są przetwarzane szybciej niż inne kluczowe obiekty HashMap. Z tego powodu jako klucze używane są głównie ciągi znaków HashMap. Mam nadzieję, że pytania wymienione w tym artykule pomogą Ci w rozmowach kwalifikacyjnych. Daj mi znać, jeśli coś pominąłem. Link do oryginału artykułu Autor: Pankaj Kumar
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION