Источник: Dev.to
Здравствуйте, коллеги-разработчики, я составил список основных вопросов на собеседовании по Java, которые должен знать каждый кодер.
1. Как в Java реверсировать строку без использования методов reverse()?
Ответ: В Java нет стандартного метода reverse(), хотя метод reverse() существует в нескольких библиотеках, таких как StringBuffer или StringBuilder. Поэтому вопрос о реверсировании массива очень часто встречается на интервью. Ниже приводится простой алгоритм, который можно использовать для реверсирования массива.
public class StringReverse {
public static void main(String[] args) {
String str = "Flexiple";
System.out.println(reverse(str));
}
public static String reverse(String in) {
if (in == null)
throw new IllegalArgumentException("Null is not valid");
StringBuilder out = new StringBuilder();
char[] chars = in.toCharArray();
for (int i = chars.length - 1; i >= 0; i--)
out.append(chars[i]);
return out.toString();
}
}
2. Напишите фрагмент кода для реализации последовательности Фибоначчи с использованием рекурсии
Ответ: Приведенный ниже фрагмент кода реализует последовательность Фибоначчи с использованием рекурсии. Этот вопрос также очень распространен на собеседованиях по Java.
public class FibonacciNumbers {
public static int fibonacci(int n) {
if (n <= 1)
return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
public static void main(String args[]) {
int n = 10;
System.out.println(fibonacci(n));
}
}
3. Как в Java удаляются пробелы из строки?
Ответ: Метод strip() — это строковый метод, который удаляет все начальные и конечные пробелы. Strip() использует внутри себя метод Character.isWhitespace() для проверки пробелов. Он определяет пробелы с помощью символов Unicodes и является рекомендуемым способом удаления пробелов. Также можно использовать альтернативные методы stripLeading() и stripTrailing(). Они помогут, если вы хотите удалить только начальные или конечные пробелы соответственно. Приведенный ниже код является примером использования метода strip().
String s = " flexiple ";
s = s.strip();
System.out.println(s);
4. Что вызывает тупиковый (deadlock) сценарий? Напишите код для создания deadlock
Ответ: Сценарий взаимоблокировки (deadlock) возникает, когда два потока требуют одинаковых блокировок для выполнения. Эти сценарии возникают, когда оба потока получили одну блокировку и ожидают получения другой блокировки. Однако, поскольку оба потока ждут выполнения другого, они блокируют друг друга, вызывая взаимоблокировку. Многопоточные программы страдают от взаимоблокировок, поскольку ключевое слово synchronized используется для обеспечения потоковой безопасности методов. Это означает, что только один поток может заблокировать и использовать синхронизированный метод. Другие потоки должны дождаться завершения текущего потока. Приведенный ниже код создает два потока, которые находятся во взаимоблокировке.
class Util
{
static void sleep(long millis)
{
try
{
Thread.sleep(millis);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
class Shared
{
synchronized void test1(Shared s2)
{
System.out.println("test1-begin");
Util.sleep(1000);
s2.test2();
System.out.println("test1-end");
}
synchronized void test2()
{
System.out.println("test2-begin");
Util.sleep(1000);
System.out.println("test2-end");
}
}
class Thread1 extends Thread
{
private Shared s1;
private Shared s2;
public Thread1(Shared s1, Shared s2)
{
this.s1 = s1;
this.s2 = s2;
}
@Override
public void run()
{
s1.test1(s2);
}
}
class Thread2 extends Thread
{
private Shared s1;
private Shared s2;
public Thread2(Shared s1, Shared s2)
{
this.s1 = s1;
this.s2 = s2;
}
@Override
public void run()
{
s2.test2(s1);
}
}
public class Deadlock
{
public static void main(String[] args)
{
Shared s1 = new Shared();
Shared s2 = new Shared();
Thread1 t1 = new Thread1(s1, s2);
t1.start();
Thread2 t2 = new Thread2(s1, s2);
t2.start();
Util.sleep(2000);
}
}
5. Напишите Java-код для печати даты в определенном формате
Ответ: Класс SimpleDateFormat помогает преобразовывать даты из одного формата в другой. Этот метод также позволяет пользователям использовать строковый формат даты и изменять его до желаемого формата. Приведенный ниже код преобразует дату в стандартный формат: ДД / ММ / ГГГГ
import java.text.SimpleDateFormat;
import java.util.Date;
public class CurrentDateTimeExample2 {
public static void main(String[] args) {
SimpleDateFormat formatter = new SimpleDateFormat("DD/MM/YYYY HH:mm:ss");
Date date = new Date();
System.out.println(formatter.format(date));
}
}
Фрагмент кода для преобразования даты в ММ / ДД / ГГГГ:
import java.text.SimpleDateFormat;
import java.util.Date;
public class CurrentDateTimeExample2 {
public static void main(String[] args) {
SimpleDateFormat formatter = new SimpleDateFormat("MM/DD/YYYY HH:mm:ss");
Date date = new Date();
System.out.println(formatter.format(date));
}
}
6. Как отсортировать HashMap по его значениям?
Ответ: HashMaps используются для реализации интерфейсов map. Они дают возможность пользователям хранить пары ключ-значение (key-value), однако ключи должны быть уникальными. HashMaps не являются упорядоченными коллекциями и их сортировка не имеет смысла, но поскольку сортировка хэш-карт может быть довольно сложной, они являются распространенным вопросом на собеседованиях по Java. В приведенном ниже коде показана реализация HashMaps.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class SortHashMap {
public static void main(String[] args) {
Map scores = new HashMap<>();
scores.put("John", 6);
scores.put("Carol", 8);
scores.put("Martin", 9);
scores.put("Mona", 7);
scores.put("Eric", 5);
System.out.println(scores);
scores = sortByValue(scores);
System.out.println(scores);
}
private static Map sortByValue(Map scores) {
Map sorted = new LinkedHashMap<>();
Set> entrySet = scores.entrySet();
System.out.println(entrySet);
List> entryList = new ArrayList<>(entrySet);
System.out.println(entryList);
entryList.sort((x, y) -> x.getValue().compareTo(y.getValue()));
System.out.println(entryList);
for (Entry e : entryList)
sorted.put(e.getKey(), e.getValue());
return sorted;
}
}
7. Что делает метод forEach()? Объясните на примере
Ответ: forEach() — это метод, который используется для перебора объектов в Java. Но в отличие от других циклов, здесь счетчик цикла не объявляется и не инициализируется, а скорее передается переменная как итерируемая (iterable). Следовательно, forEach() обычно используется с массивами или классами коллекций. Синтаксис:
for (type var : array)
{
statements using var;
}
Пример использования forEach():
class ExampleForEach
{
public static void main(String[] arg)
{
{
int[] scores = { 10, 13, 9, 11, 11};
int highest_score = maximum(scores);
System.out.println(highest_scores);
}
}
public static int maximum(int[] numbers)
{
int max = numbers[0];
// for each loop
for (int n : numbers)
{
if (n > max)
{
max = n;
}
}
return max;
}
}
8. Что такое функциональные интерфейсы и как они создаются?
Ответ: Интерфейс, содержащий только один абстрактный метод, называется функциональным интерфейсом. Впоследствии функциональные интерфейсы могут иметь только одну функцию, однако они могут содержать несколько методов по умолчанию. В Java 8 лямбда-выражения могут использоваться для создания экземпляров функциональных интерфейсов, что значительно упрощает работу. Примеры функциональных интерфейсов: ActionListener, Comparable. Вот код, используемый для определения функционального интерфейса.
@FunctionalInterface
interface Foo {
void test();
}
9. Опишите перегрузку (Overloading) на примере
Ответ: Перегрузка (Overloading) — это процесс разрешения нескольких методов с одним и тем же именем, но различающихся в зависимости от их сигнатур, типа данных или количества параметров. Перегрузка позволяет пользователю повторно использовать один метод, а не создавать и запоминать несколько методов. Короче говоря, перегрузка связана с полиморфизмом времени компиляции. Пример кода перегрузки метода:
public class Sum {
public int sum(int x, int y)
{
return (x + y);
}
public int sum(int x, int y, int z)
{
return (x + y + z);
}
public double sum(double x, double y)
{
return (x + y);
}
public static void main(String args[])
{
Sum s = new Sum();
System.out.println(s.sum(10, 20));
System.out.println(s.sum(10, 20, 30));
System.out.println(s.sum(10.5, 20.5));
}
}
10. Опишите переопределение (Overriding) на примере
Ответ: Переопределение (Overriding) — это функция в Java, которая позволяет подклассам или дочерним классам предоставлять отдельную реализацию для существующего метода в родительском классе. Когда метод подкласса имеет то же имя, параметр и тип возвращаемого значения, что и родительский класс, этот метод переопределяет метод в родительском классе. И версия вызываемого метода определяет, какой метод будет выполнен. Переопределение — это способ добиться полиморфизма во время выполнения. Пример кода переопределения метода:
class Parent {
void show()
{
System.out.println("Parent's show()");
}
}
class Child extends Parent {
@Override
void show()
{
System.out.println("Child's show()");
}
}
class Main {
public static void main(String[] args)
{
Parent obj1 = new Parent();
obj1.show();
Parent obj2 = new Child();
obj2.show();
}
}
11. Что такое бинарный поиск? А как это реализовано?
Ответ: Алгоритм двоичного (бинарного) поиска используется для поиска значения в отсортированном массиве или типе коллекции. Этот метод поиска значительно быстрее, чем методы линейного поиска. Бинарный поиск разбивает массив на более мелкие наборы, а затем применяет правила для проверки ключа ввода. Этапы реализации двоичного (бинарного) поиска:- Отсортируйте массив по возрастанию.
- Найдите среднее значение массива и сравните его с ключом.
- Если ключ равен среднему значению, верните true.
- Если false, проверьте, ключ больше или меньше среднего значения.
- Далее на основе результата проверьте ключ в верхней или нижней половине соответственно.
- Итерируйте и сравните каждое значение с ключом.
import java.util.Scanner;
public class BinarySearch {
public static void main(String[] args) {
Scanner commandReader = new Scanner(System.in);
System.out.println("Enter total number of elements : ");
int length = commandReader.nextInt();
int[] input = new int[length];
System.out.printf("Enter %d integers %n", length);
for (int i = 0; i < length; i++) {
input[i] = commandReader.nextInt();
}
System.out.println("Please enter number to be searched in array
(sorted order)");
int key = commandReader.nextInt();
int index = performBinarySearch(input, key);
if (index == -1) {
System.out.printf("Sorry, %d is not found in array %n", key);
} else {
System.out.printf("%d is found in array at index %d %n", key,
index);
}
commandReader.close();
}
public static int performBinarySearch(int[] input, int number) {
int low = 0;
int high = input.length - 1;
while (high >= low) {
int middle = (low + high) / 2;
if (input[middle] == number) {
return middle;
} else if (input[middle] < number) {
low = middle + 1;
} else if (input[middle] > number) {
high = middle - 1;
}
}
return -1;
}
}
12. Каковы лучшие методы предотвращения взаимоблокировок (deadlocks) в Java?
Ответ:- Вложенные блокировки (Nesting Locks): основная причина взаимоблокировок — это когда блокировки передаются нескольким потокам. Избегание блокирования нескольких потоков в случае, если поток с блокировкой уже существует, может помочь предотвратить взаимоблокировки.
- Использование Thread.join(): взаимоблокировки также могут возникать, когда поток ожидает ресурс из другого потока. Однако в таких случаях Thread.join() можно использовать с максимальным временем выполнения.
- Использование блокировки только при необходимости: Практикуйтесь в использовании блокировок только на элементах, когда это необходимо. Ненужные блокировки — основная причина тупиковых ситуаций.
13. Напишите код для реализации LRU-кеширования на Java
Ответ: LRU означает кеш-память, которая меньше всего использовалась. Схема кэширования LRU используется для удаления последнего использованного кеша. Этот процесс происходит, когда существующий кеш заполнен, а новая страница, на которую имеется ссылка, отсутствует в существующем кеше. В приведенном ниже коде показана реализация:
import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Iterator;
public class LRUCache {
private Deque doublyQueue;
private HashSet hashSet;
private final int CACHE_SIZE;
LRUCache(int capacity) {
doublyQueue = new LinkedList<>();
hashSet = new HashSet<>();
CACHE_SIZE = capacity;
}
public void refer(int page) {
if (!hashSet.contains(page)) {
if (doublyQueue.size() == CACHE_SIZE) {
int last = doublyQueue.removeLast();
hashSet.remove(last);
}
}
else {/* The found page may not be always the last element, even if it's an
intermediate element that needs to be removed and added to the start
of the Queue */
doublyQueue.remove(page);
}
doublyQueue.push(page);
hashSet.add(page);
}
public void display() {
Iterator itr = doublyQueue.iterator();
while (itr.hasNext()) {
System.out.print(itr.next() + " ");
}
}
public static void main(String[] args) {
LRUCache cache = new LRUCache(4);
cache.refer(1);
cache.refer(2);
cache.refer(3);
cache.refer(1);
cache.refer(4);
cache.refer(5);
cache.refer(2);
cache.refer(2);
cache.refer(1);
cache.display();
}
}
14. Как повернут массив в зависимости от позиции K, например, k = 2?
Ответ: Фрагмент кода вращает (return) массив в зависимости от указанной позиции. Хотя это кажется простым, он проверяет ваше понимание циклов и массивов и, следовательно, является распространенным вопросом на собеседованиях по Java.
public static int[] rotateBruteForce(int[] nums, int k) {
for (int i = 0; i < k; i++) {
for (int j = nums.length - 1; j > 0; j--) {
// move each number by 1 place
int temp = nums[j];
nums[j] = nums[j - 1];
nums[j - 1] = temp;
}
System.out.println("Array rotation after "+(i+1)+" step");
printArray(nums);
System.out.println();
}
return nums;
}
15. Что такое очереди (Queues) в Java? Реализуйте их с помощью массивов.
Ответ: Очереди — это линейные структуры, демонстрирующие порядок операций в порядке очереди. Java действительно обеспечивает более простые реализации для абстрактных типов данных, таких как очереди, стеки и так далее. Однако их реализация с использованием массива — это вопрос, который проверяет ваше понимание концепции. Помните, что реализация очереди в виде массива не является динамической.
package org.arpit.java2blog;
public class QueueUsingArrayMain {
private int capacity;
int queueArr[];
int front;
int rear;
int currentSize = 0;
public QueueUsingArrayMain(int sizeOfQueue) {
this.capacity = sizeOfQueue;
front = 0;
rear = -1;
queueArr = new int[this.capacity];
}
16. Что такое HeapSort? Напишите код для его реализации
Ответ: HeapSort — это метод сортировки, основанный на структуре данных двоичной (бинарной) кучи. Двоичная куча — это двоичное дерево, в котором элементы хранятся таким образом, что значения в родительском узле либо больше (max-heap), либо меньше (min-heap), чем значения в дочернем узле. Код для реализации HeapSort выглядит следующим образом:
public class HeapSort {
public void sort(int arr[])
{
int n = arr.length;
// Build heap (rearrange array)
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);
// One by one extract an element from heap
for (int i = n - 1; i > 0; i--) {
// Move current root to end
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
// call max heapify on the reduced heap
heapify(arr, i, 0);
}
}
// To heapify a subtree rooted with node i which is
// an index in arr[]. n is size of heap
void heapify(int arr[], int n, int i)
{
int largest = i; // Initialize largest as root
int l = 2 * i + 1; // left = 2*i + 1
int r = 2 * i + 2; // right = 2*i + 2
// If left child is larger than root
if (l < n && arr[l] > arr[largest])
largest = l;
// If right child is larger than largest so far
if (r < n && arr[r] > arr[largest])
largest = r;
// If largest is not root
if (largest != i) {
int swap = arr[i];
arr[i] = arr[largest];
arr[largest] = swap;
// Recursively heapify the affected sub-tree
heapify(arr, n, largest);
}
}
/* A utility function to print array of size n */
static void printArray(int arr[])
{
int n = arr.length;
for (int i = 0; i < n; ++i)
System.out.print(arr[i] + " ");
System.out.println();
}
// Driver code
public static void main(String args[])
{
int arr[] = { 12, 11, 13, 5, 6, 7 };
int n = arr.length;
HeapSort ob = new HeapSort();
ob.sort(arr);
System.out.println("Sorted array is");
printArray(arr);
}
}
17. Что такое Мемоизация (Memoization)?
Ответ: Мемоизация — это подход, который помогает решать проблемы, вызванные динамическим программированием. Этот процесс гарантирует, что данный метод не будет выполняться более одного раза для одних и тех же входных данных. Возвращаемые значения хранятся в хэш-таблицах или хэш-картах и используются повторно по мере необходимости. Приведенный ниже код является примером мемоизации в последовательности Фибоначчи.
import java.io.*;
class GFG
{
// Fibonacci Series
// using Recursion
static int fib(int n)
{
// Base case
if (n <= 1)
return n;
// recursive calls
return fib(n - 1) +
fib(n - 2);
}
// Driver Code
public static void main (String[] args)
{
int n = 6;
System.out.println(fib(n));
}
}
18. Напишите фрагмент кода для реализации пузырьковой (bubble) сортировки
Ответ: Приведенный ниже код является решением для пузырьковой сортировки, что также является распространенным вопросом на собеседованиях по Java.
public class BubbleSortExample {
static void bubbleSort(int[] arr) {
int n = arr.length;
int temp = 0;
for(int i=0; i < n; i++){
for(int j=1; j < (n-i); j++){
if(arr[j-1] > arr[j]){
//swap elements
temp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = temp;
}
}
}
}
public static void main(String[] args) {
int arr[] ={3,60,35,2,45,320,5};
System.out.println("Array Before Bubble Sort");
for(int i=0; i < arr.length; i++){
System.out.print(arr[i] + " ");
}
System.out.println();
bubbleSort(arr);//sorting array elements using bubble sort
System.out.println("Array After Bubble Sort");
for(int i=0; i < arr.length; i++){
System.out.print(arr[i] + " ");
}
}
}
19. Что такое trie-структуры данных в Java?
Ответ: Trie — это структура данных, которая хранит данные в упорядоченной древовидной структуре, используя ключи хранения. Положение узла в дереве определяет ключ, связанный с узлом, а наследники узла имеют общий префикс. Благодаря такой структуре trie-файлы предлагают лучшую производительность, а также значительно быстрее извлекают данные. Однако единственным недостатком использования дерева является то, что ему требуется больше места для хранения.20. Напишите фрагмент кода для преобразования HashMap в ArrayList
Ответ: Приведенный ниже код используется для преобразования HashMap в ArrayList.
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
public class Java8MapToListExamples
{
public static void main(String[] args)
{
//Creating a HashMap object
HashMap studentPerformanceMap = new HashMap();
//Adding elements to HashMap
studentPerformanceMap.put("John Kevin", "Average");
studentPerformanceMap.put("Rakesh Sharma", "Good");
studentPerformanceMap.put("Prachi D", "Very Good");
studentPerformanceMap.put("Ivan Jose", "Very Bad");
studentPerformanceMap.put("Smith Jacob", "Very Good");
studentPerformanceMap.put("Anjali N", "Bad");
//Getting Set of keys
Set keySet = studentPerformanceMap.keySet();
//Creating an ArrayList of keys
ArrayList listOfKeys = new ArrayList(keySet);
System.out.println("ArrayList Of Keys :");
for (String key : listOfKeys)
{
System.out.println(key);
}
System.out.println("--------------------------");
//Getting Collection of values
Collection values = studentPerformanceMap.values();
//Creating an ArrayList of values
ArrayList listOfValues = new ArrayList(values);
System.out.println("ArrayList Of Values :");
for (String value : listOfValues)
{
System.out.println(value);
}
System.out.println("--------------------------");
//Getting the Set of entries
Set> entrySet = studentPerformanceMap.entrySet();
//Creating an ArrayList Of Entry objects
ArrayList> listOfEntry = new ArrayList>(entrySet);
System.out.println("ArrayList of Key-Values :");
for (Entry entry : listOfEntry)
{
System.out.println(entry.getKey()+" : "+entry.getValue());
}
}
}
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ