Вопросы на собеседовании по Java String

Введение Без сомнения, класс String является наиболее часто используемым классом в Java, представляющим последовательность символов, рассматриваемую как объект. Учитывая типичную роль строк практически во всех приложениях Java, рекрутеры уделяют много внимания вопросам, связанным со строками, во время собеседования. При входе на собеседование Java-разработчик должен иметь полный и глубокий контроль и знание этого класса. Более того, вам также следует подготовиться к собеседованию, изучив предыдущие i.

Вступление

Без сомнения, String - это наиболее часто используемый класс в Java, представляющий последовательность символов, рассматриваемую как объект. Учитывая типичную роль String практически во всех приложениях Java, рекрутеры уделяют много внимания вопросам, связанным со String во время собеседования. При входе на собеседование Java-разработчик должен иметь полный и глубокий контроль и знание этого класса.

Более того, вам также следует подготовиться к собеседованию, изучив предыдущие вопросы собеседования, используемые ведущими компаниями, что вы можете сделать с помощью Daily Coding Problem{.dcp-link} . В DCP вам ежедневно по электронной почте отправляются практические вопросы. Хотя, если вам нужно конкретно изучить Java Strings, то читайте дальше.

Вопросы на собеседовании по Java String

На собеседовании часто можно выделить две категории вопросов - теоретические и вопросы кодирования:

Теоретические вопросы

Строковые классы

Вопрос

"Какие классы String вам знакомы?

Отвечать

Поначалу этот вопрос может показаться запутанным, но не беспокойтесь - на самом деле это довольно просто.

Строка - это последовательность символов, и String не единственный, кто это делает. В Java есть три класса, которые используются для создания объектов String : String, StringBuffer и StringBuilder . На самом деле это довольно глубокая тема при рассмотрении различий между классами и их преимуществ / недостатков.

Если вы хотите подробнее узнать об этом, ознакомьтесь с нашей статьей по этой теме - String vs StringBuilder vs StringBuffer .

Неизменяемость строк

Вопрос

«Является ли String неизменным классом, и если да, то почему?»

Отвечать

Это очень распространенный вопрос на собеседовании, и ответ «да» или «нет» обычно не подходит. Обычно вам нужно будет объяснить больше.

String - неизменный класс. Это означает, что после создания экземпляра String его нельзя изменить. Это, прежде всего, эффект final модификатора, примененного к классу String Вызов любого метода изменения содержимого в String просто вернет новый , обновленный String - исходный объект не изменится.

Это легко увидеть в исходном коде любого метода String

 public String concat(String str) { 
 int otherLen = str.length(); 
 if (otherLen == 0) { 
 return this; 
 } 
 int len = value.length; 
 char buf[] = Arrays.copyOf(value, len + otherLen); 
 str.getChars(buf, len); 
 return new String(buf, true); 
 } 

Исходная str никогда не изменяется, потому что ее нельзя изменить. В конечном итоге метод возвращает новый объект String

Пул строк

Вопрос

"Что такое пул строк?"

Отвечать

Как уже упоминалось, очень часто используются строки. Используя тот факт, что они неизменяемы, JVM сохраняет все строковые литералы в памяти кучи . Каждый раз, когда мы неявно создаем экземпляр String , его буквальное значение сравнивается с значениями в памяти кучи, и, если он уже существует, ссылочная переменная присваивается уже существующей ячейке памяти.

Такой подход может значительно сэкономить память, поскольку нет повторяющихся значений. Этот набор сохраненных ячеек памяти называется пулом строк .

Наследование строк

Вопрос

"Можете ли вы расширить String ?"

Отвечать

Поскольку класс String объявлен как final , он не может быть унаследован.

== против .equals ()

Вопрос

"Есть ли разница между оператором == .equals() ?"

Отвечать

Хотя они могут казаться одинаковыми, между этими двумя валидаторами равенства есть явное различие:

  • Оператор == проверяет равенство ссылочных переменных и возвращает true если обе указывают на один и тот же объект в памяти.
  • Метод .equals() - это метод, который сравнивает две строки на основе их содержимого и возвращает true если они равны.

Использование == для сравнения строк может вернуть ожидаемый результат из-за того, что пул строк сохраняет значения в том же месте памяти, хотя часто этого не происходит.

С другой стороны, .equals() всегда будет возвращать ожидаемый результат при сравнении строк.

Указатель символов

Вопрос

«Как вы оцениваете ценность персонажа в определенной позиции?»

Отвечать

Класс String предоставляет метод .charAt(int position) который возвращает один символ. Какой символ вернет метод, зависит от указанного аргумента 'position'.

Как и в массиве, 0 представляет индекс первого символа в .length() - 1 представляет индекс последнего символа.

Конкатенация строк

Вопрос

"Каким образом можно выполнить конкатенацию строк?"

Отвечать

Конкатенация - это операция, используемая для объединения двух строк в новую. Базовые строки могут быть объединены просто с помощью + или с помощью .concat() , в то время как StringBuffers и StringBuilders достигают конкатенации с помощью .append() .

При использовании + с другими типами данных, если возможно, они преобразуются в String.

Другой способ объединить несколько строк - использовать класс StringJoiner

 // The delimeter is "", the prefix is "[" and the suffix is "+" 
 StringJoiner joiner = new StringJoiner("", "[", "+"); 
 joiner.add("Orange") 
 .add("Apple") 
 .add("Pear"); 
 
 System.out.println(joiner.toString()); 

Результатом будет:

 [OrangeApplePear+ 

Безопасность струнных потоков

Вопрос

"Являются ли строки потокобезопасными?"

Отвечать

В Java каждый неизменяемый объект является потокобезопасным и, следовательно, String также является потокобезопасным.

Это относится и к StringBuffer поскольку он использует ключевое слово Java synchronized , но не относится к StringBuilder , который не является потокобезопасным, поскольку он изменяемый и не использует ключевое слово synchronized

Строка против StringBuilder против StringBuffer

Вопрос

"В чем разница между классами String , StringBuilder и StringBuffer

Отвечать

Строковые объекты проще в использовании, потокобезопасны и неизменяемы, что означает, что они потребляют больше памяти и медленнее, чем их братья и StringBuffer StringBuilder ), когда дело доходит до манипуляций со строками.

StringBuffer являются изменяемыми, эффективными с точки зрения памяти и потокобезопасными, но они по-прежнему медленны по сравнению с StringBuilder .

StringBuilder также являются изменяемыми, эффективными с точки зрения памяти и чрезвычайно быстрыми, но они не являются потокобезопасными.

Если вы хотите узнать больше о Strings, StringBuffers и StringBuilders , у нас есть целая статья, в которой подробно рассматривается эта тема.

Вопросы по кодированию

Переворачивание строки

Чтобы перевернуть String, нам нужно было бы написать собственную функцию, верно? Что ж, в этом случае есть обходной путь - мы можем использовать StringBuilder или StringBuffer в качестве оболочки для нашего объекта String

Таким образом, мы можем получить доступ к функции .reverse() и использовать ее для переворота нашей String без создания новой пользовательской функции для той же самой задачи:

 String str = "I'm a string waiting to be reversed"; 
 System.out.println(str); 
 
 StringBuilder stringBuilder = new StringBuilder(str); 
 stringBuilder.reverse(); 
 System.out.println("Reversing the string. . .\n"); 
 
 System.out.println(stringBuilder.toString()); 

Выход:

 I'm a string waiting to be reversed 
 Reversing the string. . . 
 
 desrever eb ot gnitiaw gnirts a m'I 

Однако, если рекрутер не одобряет использование этого обходного пути, существует множество способов изменить строковый символ за символом. Перечислим парочку:

1. Обращение по массиву символов:

 public String reverse(String str) { 
 char[] characters = str.toCharArray(); 
 int start = 0; 
 int finish = characters.length-1; 
 char temp; 
 
 while(finish > start) { 
 temp = characters[start]; 
 characters[start] = characters[finish]; 
 characters[finish] = temp; 
 finish--; 
 start++; 
 } 
 return new String(in); 
 } 

Этот подход очень эффективен, поскольку он просто меняет порядок символов и возвращает новый String с массивом, переданным конструктору.

2. Реверс путем наложения символов:

 public String reverse(String str) { 
 String result = ""; 
 for(int i = str.length() - 1; i >= 0; i--) { 
 result = result + string.charAt(i); 
 } 
 System.out.println(result); 
 } 

Хотя этот подход не так эффективен из-за создания нового объекта String путем конкатенации для каждого символа.

Проверка, содержит ли строка только цифры

Самый простой способ проверить, содержит ли строка только цифры, - использовать метод .matches() и предоставить аргумент String - "[0-9]+" . Ожидаемый аргумент должен быть регулярным выражением (Regular Expression), которому должна соответствовать строка - в нашем случае регулярное выражение представляет собой числовые символы от 0 до 9!

 String str = "09"; 
 
 if (str.matches("[0-9]+")) { 
 System.out.println("String contains only numbers."); 
 } else { 
 System.out.println("String doesn't contain only numbers!"); 
 } 

Выход:

 String contains only numbers. 

Как преобразовать строку в целое число

Класс Integer предоставляет три метода, которые позволяют нам преобразовывать строки в целые числа:

  • parseInt()
  • valueOf()
  • decode()

Они довольно просты и возвращают целые числа с переданной строкой:

 String str = "1234"; 
 int strNumber = Integer.parseInt(str); 
 int strNumber2 = Integer.valueOf(str); 
 int strNumber3 = Integer.decode(str); 
 
 System.out.println(4321 + strNumber); 
 System.out.println(4321 + strNumber); 
 System.out.println(4321 + strNumber); 

Выход:

 5555 
 5555 
 5555 

Если вы хотите прочитать все варианты использования этих методов, а также их различия, у нас есть отличная статья о преобразовании строк в целые числа, в которой эта тема рассматривается более подробно.

Удаление повторяющихся символов в строке

Чтобы удалить повторяющиеся символы в строке, мы можем использовать HashSet s, Stream s и даже LinkedList s. Но для этого конкретного примера мы собираемся использовать только String и найти решение, реализовав адекватную логику.

Прежде всего, нам нужны две строки - одна будет содержать входную строку, а другая - «отфильтрованный» результат. После этого мы создаем цикл, который должен перебирать нашу входную строку, по 1 символу за раз.

Мы будем использовать логический флаг, изначально установленный в false . Внутренний цикл выполняет итерацию по result строке, сравнивая символы из первой строки со второй:

  • Если символ отсутствует во второй строке, мы добавляем его.
  • Если символ присутствует во второй строке, мы отмечаем логический флаг как true что исключает символ из конкатенации.

Вот реализация:

 String str = "stackabuse"; 
 String str2 = ""; 
 for (int i = 0; i < str.length(); i++) { 
 boolean found = false; 
 for (int j = 0; j < str2.length(); j++) { 
 if (str.charAt(i) == str2.charAt(j)) { 
 found = true; 
 break; 
 } 
 } 
 if (found == false) { 
 str2 = str2.concat(String.valueOf(str.charAt(i))); 
 } 
 } 
 System.out.println(str2); 

Выход:

 stackbue 

Нахождение максимального числа символов в строке

Лучший способ найти максимальное количество символов в строке - использовать HashMap s. Чтобы найти нужный символ, а также количество его вхождений, наша HashMap должна содержать ключ char и значение int

Логика здесь проста - проверьте каждый символ в String и, если символ уже существует в HashMap его значение, иначе сохраните символ в HashMap и присвойте ему значение 1. Для каждого символа мы проверяем, является ли оно значением больше, чем charCount которая подсчитывает максимальное количество вхождений, и если это так, мы увеличиваем charCount .

В конце мы перебираем HashMap и ищем ключ, который имеет charCount и когда мы его находим, мы просто печатаем его. Если есть несколько символов с одинаковым charCount все они выводятся на консоль:

 public static void findMaxOccurrence(String input) { 
 int charCount = 0; 
 HashMap<Character, Integer> map = new HashMap<>(); 
 char[] inputChar = input.toCharArray(); 
 
 for (int i = 0; i < inputChar.length; i++) { 
 char c = inputChar[i]; 
 
 if (map.containsKey(c)) { 
 int count = map.get(c); 
 count++; 
 
 if (charCount < count) { 
 charCount++; 
 } 
 
 map.put(c, count); 
 } else { 
 map.put(c, 1); 
 } 
 } 
 
 Set set = map.keySet(); 
 Iterator<Character> iterator = set.iterator(); 
 while (iterator.hasNext()) { 
 char key = iterator.next(); 
 
 if (map.get(key) == charCount) { 
 System.out.println("Character '" + key + "' has the max occurrence: " + charCount + " times!"); 
 } 
 } 
 } 
 
 public static void main(String[] args) { 
 Main.findMaxOccurrence("This is the best example"); 
 } 

Выход:

 Character ' ' has the max occurrence: 4 times! 
 Character 'e' has the max occurrence: 4 times! 

Найти первый неповторяющийся символ в строке

Итак, нам нужно найти первый неповторяющийся символ в строке, это означает, что мы должны перебрать все символы этой строки, сравнить их, и как только мы найдем первый неповторяющийся символ, мы его распечатаем, и работа будет выполнена.

Это легко сделать с помощью логического флага и двух циклов. Для каждого символа мы перебираем оставшуюся часть входной строки. Если символ из первого цикла соответствует любому из символов во втором цикле, флаг устанавливается в значение true .

Если flag ложный, что означает, что мы не нашли по крайней мере два вхождения одного и того же символа, мы разбиваем и распечатываем символ:

 String str = "stackabuse"; 
 for (int i = 0; i < str.length(); i++) { 
 boolean found = false; 
 for (int j = 0; j < str.length(); j++) { 
 if (i != j) { 
 if (str.charAt(i) == str.charAt(j)) { 
 found = true; 
 } 
 } 
 } 
 if (!found) { 
 System.out.println("The first non-repeating character is: '" + str.charAt(i) + "'"); 
 break; 
 } else if (found && i == str.length() - 1) { 
 System.out.println("There is no non-repeating character in this string!"); 
 } 
 } 

Выход:

 The first non-repeating character is: 't' 

Проверка, являются ли две строки анаграммами друг друга

Для этого вопроса мы создадим собственный метод, который проверяет, являются ли две заданные строки анаграммами, и возвращает соответствующее логическое значение.

Во-первых, мы модифицируем две наши строки, удаляя все пустые места, которые у них могут быть. После того, как они обрезаны, мы сравниваем их длину - если они не имеют одинаковой длины, нет никакой возможности, что они могут быть анаграммами друг друга, поэтому в этом случае мы возвращаем false .

В противном случае мы преобразуем наши строки в символьные массивы и переводим их содержимое в строчные буквы. Наконец, Arrays.sort() вызывается для обеих строк и сортирует символы в алфавитном порядке, и мы возвращаем результат функции Arrays.equals() которая сравнивает два массива символов и возвращает true если они имеют одинаковые символы:

 public static boolean checkAnagram(String str, String str2) { 
 str = str.replaceAll("\\s", ""); 
 str2 = str2.replaceAll("\\s", ""); 
 
 if (str.length() != str2.length()) { 
 return false; 
 } else { 
 char[] strCharArray = str.toLowerCase().toCharArray(); 
 char[] strCharArray2 = str2.toLowerCase().toCharArray(); 
 
 Arrays.sort(strCharArray); 
 Arrays.sort(strCharArray); 
 
 return (Arrays.equals(strCharArray, strCharArray)); 
 } 
 } 
 
 public static void main(String[] args) { 
 String str = "stackabuse"; 
 String str2 = "Backseat Us"; 
 
 if (checkAnagram(str, str2)) { 
 System.out.println(str + " and " + str2 + " are Anagrams!"); 
 } else { 
 System.out.println(str + " and " + str2 + " are not Anagrams!"); 
 } 
 } 

Выход:

 stackabuse and Backseat Us are Anagrams! 

Подсчет количества слов в строке

Для этого мы должны разделить нашу строку на более мелкие части (слова) и использовать пробел в качестве разделителя:

 String str = "Java is an awesome programming language!"; 
 str = str.trim().replaceAll("\\s{2,}", " "); 
 String splitStr[] = str.split(" "); 
 System.out.println("The provided string '" + str + "' contains " + splitStr.length + " words!"); 

Выход:

 The provided string 'Java is an awesome programming language!' contains 6 words! 

Заключение

В этой статье мы рассмотрели общие вопросы собеседования, связанные со строками.

Если вам интересно узнать больше о вопросах для собеседования по программированию в целом, мы составили длинный список этих вопросов, включая их объяснения, реализации, визуальные представления и приложения.

Мы также настоятельно рекомендуем проверить Daily Coding Problem{.dcp-link} , если вы серьезно настроены улучшить свою способность решать вопросы программирования, которые на самом деле задают ведущие технологические компании.

comments powered by Disqus