برنامه نویسیبک اند

سوالات برتر مصاحبه کدنویسی جاوا (همراه با پاسخ)

مقدمه

اگر برای موقعیت برنامه‌نویسی جاوا مصاحبه می‌شوید، احتمالاً مهارتهای کدنویسی‌تان تست خواهد شد. چه مبتدی جاوا باشید و چه برنامه‌نویس خبره، این مقاله برخی سوالات مصاحبه‌ای رایج جاوا را—to‌همراه پاسخها—برای کمک به آمادگی‌تان فراهم می‌کند.

نکات کلیدی

  • سوالات کدنویسی مصاحبه جاوا معمولاً Manipulation رشته، الگوریتمهای آرایه، اصول OOP، بازگشتی (Recursion) و ساختارهای داده مانند LinkedList، Stack و Map را پوشش می‌دهند.
  • بیشتر مسائل رشته در جاوا با StringBuilder، Iterationِ آرایه char و متدهایی مثل replace()، strip() و charAt() حل می‌شوند—not Mutate مستقیم؛ چون String، Immutable است.
  • سوالات مرتب‌سازی، جستجو و بازگشتی معمولاً دانش Arrays.sort()، منطق Binary Search، Merge Sort و دنباله فیبوناچی را تست می‌کنند.
  • سوالات شیءگرا روی ارث‌بری، اینترفیسها، مسئله Diamond، Polymorphism و تفاوت Comparable و Comparator تمرکز دارند.
  • سوالات Multi-Thread شامل ساخت و تشخیص Deadlock، بلاکهای synchronized، wait()/notify() و Collectionهای هم‌زمانی مثل ConcurrentHashMap و BlockingQueue هستند.
  • قابلیتهای جاوا ۸+ مانند Streamها، عبارات Lambda، parallelStream() و اینترفیسهای تابعی معمولاً در مصاحبههای سطح ارشد تست می‌شوند.

۱. چطور رشته‌ای را در جاوا معکوس کنیم؟

متد Utilityای به نام reverse() در کلاس String وجود ندارد. اما می‌توانید آرایه کاراکتری از رشته بسازید و سپس از انتها به ابتدا Iterate کنید. می‌توانید کاراکترها را به StringBuilderای Append کرده و در نهایت رشته معکوس‌شده را برگردانید.

کد نمونه زیر یک راه برای معکوس کردن رشته را نشان می‌دهد:

public class StringPrograms {

 public static void main(String[] args) {
  String str = "123";

  System.out.println(reverse(str));
 }

 public static String reverse(String in) {
  if (in == null)
   throw new IllegalArgumentException("Null is not valid input");

  StringBuilder out = new StringBuilder();

  char[] chars = in.toCharArray();

  for (int i = chars.length - 1; i >= 0; i--)
   out.append(chars[i]);

  return out.toString();
 }

}

برای افزودن چک null در متد و استفاده از StringBuilder برای Append کاراکترها امتیاز اضافه بگیرید. دقت کنید Indexing در جاوا از ۰ شروع می‌شود؛ پس در حلقه for باید از chars.length - 1 شروع کنید.

۲. چطور دو عدد را بدون متغیر سوم در جاوا جابه‌جا کنیم؟

جابه‌جایی اعداد بدون متغیر سوم، فرایند سه‌مرحله‌ای است که در کد بهتر دیده می‌شود:

b = b + a; // حالا b مجموع هر دو عدد است
a = b - a; // b - a = (b + a) - a = b (یعنی a جابه‌جا شد)
b = b - a; // (b + a) - b = a (یعنی b جابه‌جا شد)

کد نمونه زیر یک راه پیاده‌سازی متد جابه‌جایی اعداد را نشان می‌دهد:

public class SwapNumbers {

public static void main(String[] args) {
 int a = 10;
 int b = 20;

    System.out.println("a is " + a + " and b is " + b);

 a = a + b;
 b = a - b;
 a = a - b;

    System.out.println("After swapping, a is " + a + " and b is " + b);
    }

}

خروجی نشان می‌دهد که مقادیر صحیح جابه‌جا شده‌اند:

a is 10 and b is 20
After swapping, a is 20 and b is 10

۳. برنامه جاوایی بنویسید که بررسی کند آیا مصوت در رشته‌ای وجود دارد

کد نمونه زیر نشان می‌دهد چطور از عبارت باقاعده برای چک اینکه رشته شامل مصوتها هست استفاده کنید:

public class StringContainsVowels {

 public static void main(String[] args) {
  System.out.println(stringContainsVowels("Hello")); // true
  System.out.println(stringContainsVowels("TV")); // false
 }

 public static boolean stringContainsVowels(String input) {
  return input.toLowerCase().matches(".*[aeiou].*");
 }

}

۴. برنامه جاوایی بنویسید که بررسی کند آیا عدد داده‌شده اول است

می‌توانید برنامه‌ای بنویسید که عدد داده‌شده n را بر اعدادی از ۲ تا n/2 تقسیم کرده و باقیمانده را چک کند. اگر باقیمانده ۰ باشد، عدد اول نیست. کد نمونه زیر یک راه برای چک اول بودن عدد است:

public class PrimeNumberCheck {

 public static void main(String[] args) {
  System.out.println(isPrime(19)); // true
  System.out.println(isPrime(49)); // false
 }

 public static boolean isPrime(int n) {
  if (n == 0 || n == 1) {
   return false;
  }
  if (n == 2) {
   return true;
  }
  for (int i = 2; i <= n / 2; i++) {
   if (n % i == 0) {
    return false;
   }
  }

  return true;
 }

}

هرچند این برنامه کار می‌کند، از نظر حافظه و زمان خیلی کارآمد نیست. در نظر بگیرید که برای عدد N، اگر عدد اولِ M بین ۲ تا √N (جذر N) وجود داشته باشد که آن را به‌طور مساوی تقسیم کند، N اول نیست.

۵. برنامه جاوایی بنویسید که دنباله فیبوناچی را با بازگشتی چاپ کند

دنباله فیبوناچی دنباله‌ای است که هر عدد در آن مجموع دو عدد قبلی است. در این مثال، دنباله با ۰ و ۱ شروع می‌شود. کد نمونه زیر نشان می‌دهد چطور از حلقه for برای چاپ دنباله فیبوناچی استفاده کنید:

public class PrintFibonacci {

 public static void printFibonacciSequence(int count) {
  int a = 0;
  int b = 1;
  int c = 1;

  for (int i = 1; i <= count; i++) {
   System.out.print(a + ", ");

            a = b;
   b = c;
   c = a + b;
  }
 }

 public static void main(String[] args) {
     printFibonacciSequence(10);
 }

}
0, 1, 1, 2, 3, 5, 8, 13, 21, 34,

هم‌چنین می‌توانید از بازگشتی برای چاپ دنباله فیبوناچی استفاده کنید؛ چون عدد فیبوناچی با جمع دو عدد قبلی در دنباله تولید می‌شود:

F(N) = F(N-1) + F(N-2)

کلاس نمونه زیر نشان می‌دهد چطور از بازگشتی برای محاسبه دنباله فیبوناچی ۱۰-عددی استفاده کنید:

public class PrintFibonacciRecursive {

    public static int fibonacci(int count) {
  if (count <= 1)
   return count;

  return fibonacci(count - 1) + fibonacci(count - 2);
 }

 public static void main(String args[]) {
     int seqLength = 10;

     System.out.print("A Fibonacci sequence of " + seqLength + " numbers: ");

     for (int i = 0; i < seqLength; i++) {
           System.out.print(fibonacci(i) + " ");
     }
   }

}
Output
A Fibonacci sequence of 10 numbers: 0 1 1 2 3 5 8 13 21 34

۶. چطور چک کنیم لیستی از اعداد صحیح فقط شامل اعداد فرد است؟

می‌توانید از حلقه for استفاده کرده و چک کنید که هر عنصر فرد است:

public static boolean onlyOddNumbers(List<Integer> list) {
 for (int i : list) {
  if (i % 2 == 0)
   return false;
 }

 return true;
}

اگر لیست بزرگ است، برای پردازش سریع‌تر می‌توانید از Stream موازی استفاده کنید:

public static boolean onlyOddNumbers(List<Integer> list) {
 return list
   .parallelStream() // stream موازی برای پردازش سریع‌تر
   .anyMatch(x -> x % 2 != 0); // به‌محض مطابقت هر عنصر با شرط برگردانید
}

۷. چطور چک کنیم رشته‌ای Palindrome است؟

رشته Palindrome، رشته‌ای است که از هر دو جهت (جلو و عقب) یکسان است. برای چک Palindrome، می‌توانید رشته ورودی را معکوس کرده و چک کنید که نتیجه با ورودی برابر است. کد نمونه زیر نشان می‌دهد چطور از متد charAt(int index) برای چک رشتههای Palindrome استفاده کنید:

boolean checkPalindromeString(String input) {
 boolean result = true;
 int length = input.length();

 for (int i = 0; i < length/2; i++) {
  if (input.charAt(i) != input.charAt(length - i - 1)) {
   result = false;
   break;
  }
 }

 return result;
}

۸. چطور فاصله‌ها را از رشته در جاوا حذف کنیم؟

کد نمونه زیر یک راه برای حذف فاصله‌ها از رشته با متد Character.isWhitespace() را نشان می‌دهد:

String removeWhiteSpaces(String input) {
 StringBuilder output = new StringBuilder();
 
 char[] charArray = input.toCharArray();
 
 for (char c : charArray) {
  if (!Character.isWhitespace(c))
   output.append(c);
 }
 
 return output.toString();
}

۹. چطور فاصله‌های ابتدا و انتها را از رشته حذف کنیم؟

کلاس String دو متد برای حذف Whitespaceهای ابتدایی و انتهایی دارد: trim() و strip(). متد strip() در جاوا ۱۱ به کلاس String اضافه شد. متد strip() از Character.isWhitespace() برای چک اینکه کاراکتر Whitespace است استفاده می‌کند. این متد از Code Pointهای Unicode استفاده می‌کند؛ در حالی که متد trim() هر کاراکتری با مقدار Code Point کمتر یا مساوی U+0020 را Whitespace تلقی می‌کند.

متد strip() روش توصیه‌شده برای حذف Whitespaceهاست—چون از استاندارد Unicode استفاده می‌کند. کد نمونه زیر نشان می‌دهد چطور از strip() استفاده کنید:

String s = "  abc  def\t";
  
s = s.strip();
  
System.out.println(s);

چون String، Immutable است، باید خروجی strip() را به رشته Assign کنید.

۱۰. چطور آرایه‌ای را در جاوا مرتب کنیم؟

کلاس Utility یعنی Arrays متدهای sort() Overload زیادی برای مرتب‌سازی آرایههای Primitive و Object دارد. اگر آرایه Primitiveای را در ترتیب طبیعی مرتب می‌کنید، می‌توانید از Arrays.sort() استفاده کنید:

int[] array = {1, 2, 3, -1, -2, 4};

Arrays.sort(array);

System.out.println(Arrays.toString(array));

اما اگر آرایه‌ای از Objectها را مرتب می‌کنید، Object باید اینترفیس Comparable را پیاده کند. اگر می‌خواهید معیار مرتب‌سازی تعیین کنید، می‌توانید Comparator را برای منطق مرتب‌سازی پاس بدهید.

۱۱. چطور سناریوی Deadlock را برنامه‌ای در جاوا بسازیم؟

Deadlock سناریویی در محیط Multi-Thread جاواست که دو یا چند Thread برای همیشه بلاک می‌شوند. کد نمونه زیر سناریوی Deadlock را می‌سازد:

public class ThreadDeadlock {

    public static void main(String[] args) throws InterruptedException {
        Object obj1 = new Object();
        Object obj2 = new Object();
        Object obj3 = new Object();
    
        Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");
        Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");
        Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3");
        
        t1.start();
        Thread.sleep(5000);
        t2.start();
        Thread.sleep(5000);
        t3.start();        
    }

}

class SyncThread implements Runnable {

    private Object obj1;
    private Object obj2;

    public SyncThread(Object o1, Object o2) {
        this.obj1 = o1;
        this.obj2 = o2;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();

        System.out.println(name + " acquiring lock on " + obj1);
        synchronized (obj1) {
            System.out.println(name + " acquired lock on " + obj1);
            work();
            System.out.println(name + " acquiring lock on " + obj2);
            synchronized (obj2) {
                System.out.println(name + " acquired lock on " + obj2);
                work();
            }
            System.out.println(name + " released lock on " + obj2);
        }
        System.out.println(name + " released lock on " + obj1);
        System.out.println(name + " finished execution.");
    }

    private void work() {
        try {
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

هر سه Thread قادر خواهند بود قفل روی Object اول را بگیرند. اما—they از منابع مشترک استفاده کرده و به شکلی شروع شده‌اند که برای گرفتن قفل روی Object دوم، به‌طور نامحدود منتظر می‌مانند. می‌توانید از Thread Dump جاوا برای تشخیص Deadlockها استفاده کنید.

۱۲. چطور فاکتوریل عدد صحیح را در جاوا پیدا کنیم؟

فاکتوریل عدد صحیح با ضرب همه اعداد از ۱ تا عدد داده‌شده محاسبه می‌شود:

F(n) = F(1)*F(2)...F(n-1)*F(n)

کد نمونه زیر نشان می‌دهد چطور از بازگشتی برای یافتن فاکتوریل استفاده کنید:

public static long factorial(long n) {
 if (n == 1)
  return 1;
 else
  return (n * factorial(n - 1));
}

۱۳. چطور LinkedList را در جاوا معکوس کنیم؟

متد descendingIterator() مربوط به LinkedList، Iteratorای را برمی‌گرداند که روی عناصر به‌ترتیب معکوس Iterate می‌کند. کد نمونه زیر نشان می‌دهد چطور از این Iterator برای ساخت LinkedList جدیدی با عناصر مرتب به‌ترتیب معکوس استفاده کنید:

LinkedList<Integer> ll = new LinkedList<>();

ll.add(1);
ll.add(2);
ll.add(3);

System.out.println(ll);

LinkedList<Integer> ll1 = new LinkedList<>();

ll.descendingIterator().forEachRemaining(ll1::add);

System.out.println(ll1);

۱۴. چطور Binary Search را در جاوا پیاده کنیم؟

عناصر آرایه برای پیاده Binary Search باید مرتب باشند. الگوریتم Binary Search بر اساس شرایط زیر استوار است:

  • اگر Key از عنصر میانی کوچکتر باشد، حالا فقط باید در نیمه اول آرایه جستجو کنید.
  • اگر Key از عنصر میانی بزرگتر باشد، فقط باید در نیمه دوم آرایه جستجو کنید.
  • اگر Key با عنصر میانی آرایه برابر باشد، جستجو تمام می‌شود.
  • در نهایت، اگر Key در کل آرایه پیدا نشد، باید -۱ برگردانده شود. این یعنی عنصر موجود نیست.

کد نمونه زیر Binary Search را پیاده می‌کند:

public static int binarySearch(int arr[], int low, int high, int key) {
 int mid = (low + high) / 2;

 while (low <= high) {
  if (arr[mid] < key) {
   low = mid + 1;
  } else if (arr[mid] == key) {
   return mid;
  } else {
   high = mid - 1;
  }
  mid = (low + high) / 2;
 }

 if (low > high) {
  return -1;
 }

 return -1;
}

۱۵. برنامه جاوایی بنویسید که Merge Sort را نشان دهد

Merge Sort یکی از کارآمدترین الگوریتمهای مرتب‌سازی است. روی اصل «تقسیم و حل» (Divide and Conquer) کار می‌کند. بر اساس ایده شکستن لیستی به چند زیرلیست تا وقتی هر زیرلیست فقط یک عنصر داشته باشد؛ و سپس Merge کردن آن زیرلیستها به شکلی که به لیست مرتب منجر شود. کد نمونه زیر یک راه استفاده از Merge Sort را نشان می‌دهد:

public class MergeSort {

 public static void main(String[] args) {
  int[] arr = { 70, 50, 30, 10, 20, 40, 60 };

  int[] merged = mergeSort(arr, 0, arr.length - 1);

  for (int val : merged) {
   System.out.print(val + " ");
  }
 }

 public static int[] mergeTwoSortedArrays(int[] one, int[] two) {
  int[] sorted = new int[one.length + two.length];

  int i = 0;
  int j = 0;
  int k = 0;

  while (i < one.length && j < two.length) {
   if (one[i] < two[j]) {
    sorted[k] = one[i];
    k++;
    i++;
   } else {
    sorted[k] = two[j];
    k++;
    j++;
   }
  }

  if (i == one.length) {
   while (j < two.length) {
    sorted[k] = two[j];
    k++;
    j++;
   }
  }

  if (j == two.length) {
   while (i < one.length) {
    sorted[k] = one[i];
    k++;
    i++;
   }
  }

  return sorted;
 }

 public static int[] mergeSort(int[] arr, int lo, int hi) {
  if (lo == hi) {
   int[] br = new int[1];
   br[0] = arr[lo];

   return br;
  }

  int mid = (lo + hi) / 2;

  int[] fh = mergeSort(arr, lo, mid);
  int[] sh = mergeSort(arr, mid + 1, hi);

  int[] merged = mergeTwoSortedArrays(fh, sh);

  return merged;
 }

}

۱۶. آیا می‌توانید هرم کاراکترها را در جاوا بسازید؟

برنامههای الگو، موضوع مصاحبه بسیار محبوبی هستند. این نوع سوال برای فهم تواناییهای تفکر منطقی مصاحبه‌شونده استفاده می‌شود. برای مثالهای روشهای مختلف ساخت الگوهای هرمی، راهنمای «برنامههای الگوی هرمی در جاوا» را در پارمین کلود ببینید.

۱۷. برنامه جاوایی بنویسید که چک کند دو آرایه عناصر یکسان دارند

برای چک اینکه دو آرایه عناصر یکسان دارند، اول باید مجموعه عناصری از هر دو آرایه بسازید؛ سپس عناصر این مجموعه‌ها را مقایسه کنید تا بفهمید عنصری هست که در هر دو مجموعه نباشد. کد نمونه زیر نشان می‌دهد:

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class ArraySameElements {

 public static void main(String[] args) {
  Integer[] a1 = {1,2,3,2,1};
  Integer[] a2 = {1,2,3};
  Integer[] a3 = {1,2,3,4};
  
  System.out.println(sameElements(a1, a2));
  System.out.println(sameElements(a1, a3));
 }

 static boolean sameElements(Object[] array1, Object[] array2) {
  Set<Object> uniqueElements1 = new HashSet<>(Arrays.asList(array1));
  Set<Object> uniqueElements2 = new HashSet<>(Arrays.asList(array2));
  
  // اگر حجم متفاوت باشد، یعنی عدم تطابق وجود خواهد داشت
  if (uniqueElements1.size() != uniqueElements2.size()) return false;
  
  for (Object obj : uniqueElements1) {
   // عنصر در هر دو موجود نیست؟
   if (!uniqueElements2.contains(obj)) return false;
  }
  
  return true;
 }

}
true
false

۱۸. چطور مجموع همه عناصر آرایه صحیح را در جاوا بگیریم؟

می‌توانید از حلقه for برای Iterate روی عناصر آرایه و جمع‌زدن‌شان برای گرفتن مجموع نهایی استفاده کنید:

int[] array = { 1, 2, 3, 4, 5 };

int sum = 0;

for (int i : array)
 sum += i;

System.out.println(sum);

۱۹. چطور دومین عدد بزرگ آرایه را در جاوا پیدا کنیم؟

راههای زیادی برای حل این مسئله وجود دارد. می‌توانید آرایه را در ترتیب صعودی طبیعی مرتب کرده و مقدار یکی-مانده-به-آخر را بگیرید. اما مرتب‌سازی عملیات پرهزینه‌ای است. هم‌چنین می‌توانید از دو متغیر برای یافتن دومین مقدار بزرگ در یک Iteration منفرد استفاده کنید:

private static int findSecondHighest(int[] array) {
 int highest = Integer.MIN_VALUE;
 int secondHighest = Integer.MIN_VALUE;

 for (int i : array) {
  if (i > highest) {
   secondHighest = highest;
   highest = i;
  } else if (i > secondHighest) {
   secondHighest = i;
  }

 }
 return secondHighest;
}

۲۰. چطور آرایه را در جاوا بُر بزنیم (Shuffle)؟

کد نمونه زیر نشان می‌دهد چطور از کلاس Random برای تولید شمارههای Index تصادفی و بُر زدن عناصر استفاده کنید:

int[] array = { 1, 2, 3, 4, 5, 6, 7 };

Random rand = new Random();

for (int i = 0; i < array.length; i++) {
 int randomIndexToSwap = rand.nextInt(array.length);
 int temp = array[randomIndexToSwap];
 array[randomIndexToSwap] = array[i];
 array[i] = temp;
}

System.out.println(Arrays.toString(array));

می‌توانید کد بُرزدن را درون حلقه for دیگری اجرا کنید تا چند دور بُر زده شود.

۲۱. چطور رشته‌ای را در فایل متنی در جاوا پیدا کنیم؟

کد نمونه زیر نشان می‌دهد چطور از کلاس Scanner برای خواندن محتوای فایل خط-به-خط و سپس استفاده از متد contains() برای چک اینکه رشته در فایل موجود است استفاده کنید:

boolean findStringInFile(String filePath, String str) throws FileNotFoundException {
 File file = new File(filePath);

 Scanner scanner = new Scanner(file);

 // فایل را خط به خط بخوان
 while (scanner.hasNextLine()) {
  String line = scanner.nextLine();
  if (line.contains(str)) {
   scanner.close();
   return true;
  }
 }
 scanner.close();

 return false;
}

دقت کنید کد نمونه فرض می‌کند رشته‌ای که در فایل جستجو می‌کنید، کاراکتر خط جدید ندارد.

۲۲. چطور تاریخ را با Format خاص در جاوا چاپ کنیم؟

کد نمونه زیر نشان می‌دهد چطور از کلاس SimpleDateFormat برای Format کردن رشته تاریخ استفاده کنید:

String pattern = "MM-dd-yyyy";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);

String date = simpleDateFormat.format(new Date());
System.out.println(date); // 06-23-2020

۲۳. چطور دو لیست را در جاوا Merge کنیم؟

کد نمونه زیر نشان می‌دهد چطور از متد addAll() برای Merge کردن چند لیست استفاده کنید:

List<String> list1 = new ArrayList<>();
list1.add("1");
List<String> list2 = new ArrayList<>();
list2.add("2");

List<String> mergedList = new ArrayList<>(list1);
mergedList.addAll(list2);
System.out.println(mergedList); // [1, 2]

۲۴. برنامه جاوایی بنویسید که HashMap را بر اساس مقدار مرتب کند

HashMap، Collection مرتب نیست. کد نمونه زیر نشان می‌دهد چطور Entryها را بر اساس مقدار مرتب کرده و در LinkedHashMap—which ترتیب درج را حفظ می‌کند—ذخیره کنید:

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 SortHashMapByValue {

 public static void main(String[] args) {
  Map<String, Integer> scores = new HashMap<>();

  scores.put("David", 95);
  scores.put("Jane", 80);
  scores.put("Mary", 97);
  scores.put("Lisa", 78);
  scores.put("Dino", 65);

  System.out.println(scores);

  scores = sortByValue(scores);

  System.out.println(scores);
 }

 private static Map<String, Integer> sortByValue(Map<String, Integer> scores) {
  Map<String, Integer> sortedByValue = new LinkedHashMap<>();

  // مجموعه entry را بگیر
  Set<Entry<String, Integer>> entrySet = scores.entrySet();

  // چون set نامرتب است لیست بساز
  List<Entry<String, Integer>> entryList = new ArrayList<>(entrySet);

  // لیست را بر اساس مقدار مرتب کن
  entryList.sort((x, y) -> x.getValue().compareTo(y.getValue()));

  // hash map جدید را پر کن
  for (Entry<String, Integer> e : entryList)
   sortedByValue.put(e.getKey(), e.getValue());

  return sortedByValue;
 }

}

۲۵. چطور همه موارد کاراکتر داده‌شده را از رشته ورودی حذف کنیم؟

کلاس String متدی برای حذف کاراکترها ندارد. کد نمونه زیر نشان می‌دهد چطور از replace() برای ساخت رشته جدید بدون کاراکتر داده‌شده استفاده کنید:

String str1 = "abcdABCDabcdABCD";
  
str1 = str1.replace("a", ""); 

System.out.println(str1); // bcdABCDbcdABCD

String در جاوا Immutable است. همه متدهای Manipulation رشته، رشته جدیدی برمی‌گردانند—which دلیل نیاز به Assign کردن آن به متغیر دیگری است.

۲۶. چطور کاراکترهای متمایز و تعدادشان را در رشته بگیریم؟

می‌توانید آرایه کاراکتری از رشته بسازید. سپس رویش Iterate کرده و HashMapای با کاراکتر به‌عنوان Key و تعدادشان به‌عنوان Value بسازید:

String str1 = "abcdABCDabcd";

char[] chars = str1.toCharArray();

Map<Character, Integer> charsCount = new HashMap<>();

for (char c : chars) {
 if (charsCount.containsKey(c)) {
  charsCount.put(c, charsCount.get(c) + 1);
 } else
  charsCount.put(c, 1);
}

System.out.println(charsCount); // {a=2, A=1, b=2, B=1, c=2, C=1, d=2, D=1}

۲۷. آیا می‌توانید Programmatically ثابت کنید شیء String در جاوا Immutable است؟

کد نمونه زیر نشان می‌دهد چطور ثابت کنید String، Immutable است:

String s1 = "Java"; // رشته "Java" در pool ساخته و reference به s1 داده شد

String s2 = s1; //s2 هم همان reference به "Java" در pool را دارد

System.out.println(s1 == s2); // اثبات اینکه s1 و s2 همان reference را دارند

s1 = "Python"; 
// مقدار s1 در بالا تغییر کرد، پس چطور String غیرقابل-تغییر است؟

// در مورد بالا رشته جدیدی "Python" در pool ساخته شد
// s1 حالا به رشته جدید در pool اشاره می‌کند
// اما رشته اصلی "Java" همچنان بدون تغییر در pool می‌ماند
// s2 همچنان به رشته اصلی "Java" در pool اشاره می‌کند

// اثبات اینکه s1 و s2 referenceهای متفاوتی دارند
System.out.println(s1 == s2); 

System.out.println(s2); 
// "Java" چاپ می‌کند و این واقعیت را تقویت می‌کند که مقدار اصلی تغییر نکرده، پس String غیرقابل-تغییر است

۲۸. آیا می‌توانید کدی بنویسید که ارث‌بری را در جاوا نشان دهد؟

کد نمونه زیر نشان می‌دهد چطور از کلیدواژه extends برای ساخت زیرکلاس کلاس Animal استفاده کنید. کلاس جدید Cat، متغیر را از کلاس Animal به ارث برده و کد بیشتری اضافه می‌کند که فقط به Cat تعلق دارد:

class Animal {
 String color;
}

class Cat extends Animal {
 void meow() {
  System.out.println("Meow");
 }
}

۲۹. چطور مسئله Diamond با ارث‌بری چندگانه را نشان دهیم؟

مسئله Diamond وقتی رخ می‌دهد که کلاسی از چند کلاس ارث ببرد و وقتی نامشخص است کدام متد از کدام کلاس اجرا شود، ابهامی ایجاد شود. جاوا برای اجتناب از این مشکل، Extend کردن چند کلاس را اجازه نمی‌دهد:

interface I {
 void foo();
}
class A implements I {
 public void foo() {}
}

class B implements I {
 public void foo() {}
}

class C extends A, B { // کامپایل نمی‌شود
 public void bar() {
  super.foo();
 }
}

۳۰. چطور مثال try-catch را در جاوا نشان دهیم؟

try {
 FileInputStream fis = new FileInputStream("test.txt");
} catch(FileNotFoundException e) {
 e.printStackTrace();
}

از جاوا ۷ به بعد، می‌توانید چند Exception را در بلاک catch منفردی هم بگیرید—که وقتی همان کد را در همه بلاکهای catch دارید مفید است:

public static void foo(int x) throws IllegalArgumentException, NullPointerException {
 // کدی
}

public static void main(String[] args) {
 try {
  foo(10);
 } catch (IllegalArgumentException | NullPointerException e) {
  System.out.println(e.getMessage());
 }
}

۳۱. برنامه جاوایی بنویسید که NullPointerException را نشان دهد

اگر تابعی را روی null صدا بزنید، NullPointerException پرتاب می‌کند:

public static void main(String[] args) {
 printString(null, 3);
 
}

static void printString(String s, int count) {
 for (int i = 0; i < count; i++) {
  System.out.println(s.toUpperCase()); // Exception in thread "main" java.lang.NullPointerException
 }
}

باید چک null برای Validation زودهنگام داشته باشید:

static void printString(String s, int count) {
 if (s == null) return;
 for (int i = 0; i < count; i++) {
  System.out.println(s.toUpperCase());
 }
}

۳۲. چطور Record در جاوا بسازیم؟

Record در جاوا ۱۶ به‌عنوان قابلیت استاندارد اضافه شد. Recordها امکان ساخت کلاس POJO را با کد مینیمال فراهم می‌کنند. Recordها خودکار کد hashCode()، equals()، متدهای Getter و متد toString() را تولید می‌کنند. Recordها Final بوده و ضمناً کلاس java.lang.Record را Extend می‌کنند:

import java.util.Map;
 
public record EmpRecord(int id, String name, long salary, Map<String, String> addresses) {
}

۳۳. چطور Text Block در جاوا بسازیم؟

جاوا ۱۵ قابلیت Text Block را اضافه کرد. می‌توانید رشتههای چندخطی با Text Block بسازید. رشته چندخطی باید درون جفت سه-کوتیشن نوشته شود:

String textBlock = """
  Hi
  Hello
  Yes""";

همان ساخت رشته‌ای مثل “Hi\nHello\nYes” است.

۳۴. مثالی از Switch Expression و دستورات case چند-Label نشان دهید

int choice = 2;

int x = switch (choice) {
    case 1, 2, 3:
     yield choice;
    default:
     yield -1;
};

System.out.println("x = " + x); // x = 2

هم‌چنین می‌توانید از عبارات Lambda در Switch Expression استفاده کنید:

String day = "TH";
String result = switch (day) {
    case "M", "W", "F" -> "MWF";
    case "T", "TH", "S" -> "TTS";

    default -> {
     if (day.isEmpty())
      yield "Please insert a valid day.";
     else
      yield "Looks like a Sunday.";
    }
};

System.out.println(result); // TTS

۳۵. چطور کلاس جاوایی را از خط فرمان کامپایل و اجرا کنیم؟

public class Test {

public static void main(String args[]) {
  System.out.println("Hi");
 }

}

با این دستور در Terminal کامپایلش کنید:

javac Test.java

برای اجرای کلاس، از این دستور استفاده کنید:

java Test

در Releaseهای اخیر، دستور java اگر فایل کلاس موجود نباشد برنامه را کامپایل هم می‌کند. اگر کلاس در Packageای مانند com.example است، باید درون پوشه com/example باشد:

java com/example/Test.java

اگر کلاس‌تان برای کامپایل و اجرا به JARهای اضافی نیاز دارد، از گزینه java -cp استفاده کنید:

java -cp .:~/.m2/repository/log4j/log4j/1.2.17/log4j-1.2.17.jar com/example/Test.java

۳۶. چطور Enum در جاوا بسازیم؟

public enum ThreadStates {
 START,
 RUNNING,
 WAITING,
 DEAD;
}

ThreadStates، Enum با فیلدهای ثابتِ مشخص START، RUNNING، WAITING و DEAD است. همه Enumها ضمناً کلاس java.lang.Enum را Extend کرده و اینترفیسهای Serializable و Comparable را پیاده می‌کنند. Enumها می‌توانند متد هم داشته باشند.

۳۷. چطور از متد forEach() در جاوا استفاده کنیم؟

List<String> list = new ArrayList<>();

Iterator<String> it = list.iterator();

while (it.hasNext()) {
 System.out.println(it.next());
}

می‌توانید با عبارت Lambda از forEach() برای کاهش حجم کد استفاده کنید:

List<String> list = new ArrayList<>();

list.forEach(System.out::print);

۳۸. چطور اینترفیس با متد default و static بنویسیم؟

جاوا ۸ متدهای default و static را در اینترفیسها معرفی کرد. این، شکاف بین اینترفیسها و کلاسهای Abstract را پر کرد:

public interface Interface1 {
 
 // متد abstract معمولی
 void method1(String str);
 
 default void log(String str) {
  System.out.println("I1 logging::" + str);
 }
 
 static boolean isNull(String str) {
  System.out.println("Interface Null Check");

  return str == null ? true : "".equals(str) ? true : false;
 }

}

۳۹. چطور اینترفیس تابعی بسازیم؟

اینترفیس با دقیقاً یک متد Abstract، اینترفیس تابعی نامیده می‌شود. مزیت اصلیشان این است که می‌توانید از عبارات Lambda برای Instantiate کردن‌شان استفاده کرده و از پیاده‌سازی سنگین کلاس Anonymous اجتناب کنید:

@FunctionalInterface
interface Foo {
 void test();
}

۴۰. مثالی از استفاده عبارات Lambda نشان دهید

Runnable مثال عالیِ اینترفیس تابعی است:

Runnable r1 = () -> System.out.println("My Runnable");

۴۱. مثالاتی از Overloading و Overriding نشان دهید

وقتی کلاسی دو یا چند متد هم‌نام دارد، Overloaded نامیده می‌شوند:

class Foo {
 void print(String s) {
  System.out.println(s);
 }

 void print(String s, int count) {
  while (count > 0) {
   System.out.println(s);
   count--;
  }
 }

}

وقتی متد Superclass در کلاس فرزند هم پیاده شود، Overriding نامیده می‌شود:

class Base {
 void printName() {
  System.out.println("Base Class");
 }
}

class Child extends Base {
 @Override
 void printName() {
  System.out.println("Child Class");
 }
}

۴۲ تا ۴۹. خروجی را حدس بزنید

با حدس زدن خروجی قطعهکدهای زیر خودتان را تست کنید.

۴۲.

String s1 = "abc";
String s2 = "abc";

System.out.println("s1 == s2 is:" + s1 == s2);

۴۳.

String s3 = "JournalDev";
int start = 1;
char end = 5;

System.out.println(s3.substring(start, end));

۴۴.

HashSet shortSet = new HashSet();

 for (short i = 0; i < 100; i++) {
    shortSet.add(i);
    shortSet.remove(i - 1);
}

System.out.println(shortSet.size());

۴۵.

try {
 if (flag) {
    while (true) {
     }
    } else {
     System.exit(1);
    }
} finally {
    System.out.println("In Finally");
}

۴۶.

String str = null;
String str1="abc";

System.out.println(str1.equals("abc") | str.equals(null));

۴۷.

String x = "abc";
String y = "abc";

x.concat(y);

System.out.print(x);

۴۸.

public class MathTest {

  public void main(String[] args) {    
     int x = 10 * 10 - 10;
     
     System.out.println(x);
    }
   
}

۴۹.

public class Test {
   
   public static void main(String[] args) {
     try {
      throw new IOException("Hello");
     } catch(IOException | Exception e) {
      System.out.println(e.getMessage());
     }
    }
}

۵۰. ۵ اشتباه در قطعه کد زیر پیدا کنید

package com.digitalocean.programming-interviews;

public class String Programs {

 static void main(String[10] args) {
  String s = "abc"
  System.out.println(s);
 }
}

پاسخ‌ها:

۱. نام کلاس فاصله دارد: «String Programs» — نام کلاس معتبر نیست.
۲. متد main باید public باشد، نه فقط static.
۳. تعریف آرایه String[10] args نامعتبر است — باید String[] args باشد.
۴. سمی‌کالن (;) بعد از "abc" جا افتاده.
۵. نام Package باید با حروف کوچک باشد (قرارداد، اگرچه خطای کامپایل نیست).

سوالات اضافی

مقایسه واضح: Collection در مقابل Stream

Collection و Stream دو مفهوم بنیادی در جاوایند که اهداف متفاوتی در مدیریت داده خدمت می‌کنند.

Collectionها:

  • Collection، گروهی از Objectهاست که می‌تواند به‌عنوان واحد منفردی Manipulate شود.
  • ساختار داده ایستایی است که عناصر را ذخیره و متدهایی برای دسترسی، تغییر و Manipulate فراهم می‌کند.
  • مثالها: List، Set، Map و Queue.
  • برای سناریوهایی که داده باید ساختاریافته ذخیره و Manipulate شود مناسب‌اند.

Streamها:

  • Stream، دنباله‌ای از عناصر است که می‌تواند به سبک پایپ‌لاین پردازش شود.
  • ساختار داده داینامیکی است که امکان ساخت پایپ‌لاین عملیاتها برای پردازش عناصر را می‌دهد.
  • Streamها برای پردازش موازی طراحی شده و برای مجموعه دادههای بزرگ مفیدند.
  • برای سناریوهایی که داده باید به سبک برنامه‌نویسی تابعی پردازش شود مناسب‌اند.

تفاوت‌های کلیدی:

  • ذخیره‌سازی: Collectionها عناصر را ذخیره می‌کنند؛ Streamها ذخیره نمی‌کنند—بلکه هم‌زمان پردازش می‌کنند.
  • پردازش: Collectionها ترتیبی پردازش می‌شوند؛ Streamها می‌توانند موازی پردازش شوند.
  • Lazy در مقابل Eager: Streamها Lazy هستند—عملیاتها فقط وقتی عملیات Terminal فراخوانی شود اجرا می‌شوند. Collectionها Eager هستند—همه عملیاتها فوراً اجرا می‌شوند.

چالشهای کدنویسی Multi-Thread و هم‌زمانی جاوا

چند چالش کدنویسی Multi-Thread و هم‌زمانی جاوا برای تمرین:

۱. کلاس Singleton امن-برای-Thread پیاده کنید.
۲. برنامه‌ای بنویسید که استفاده از بلاکهای synchronized برای دستیابی به Thread Safety را نمایش دهد.
۳. مسئله Producer-Consumer را با متدهای wait() و notify() پیاده کنید.
۴. از ExecutorService جاوا برای اجرای لیستی از وظایف به‌صورت هم‌زمان استفاده کنید.
۵. Cache امن-برای-Thread با ConcurrentHashMap پیاده کنید.
۶. برنامه‌ای بنویسید که استفاده از متغیرهای Atomic برای عملیاتهای امن-برای-Thread را نمایش دهد.
۷. سناریوی Deadlock پیاده کرده و توضیح بدهید چطور از آن اجتناب کنید.
۸. از اینترفیس Lock جاوا برای پیاده قفل سفارشی برای Synchronize کردن Thread استفاده کنید.
۹. صف امن-برای-Thread با BlockingQueue پیاده کنید.
۱۰. برنامه‌ای بنویسید که استفاده از CompletableFuture برای برنامه‌نویسی غیرهمگام را نمایش دهد.

سوالات متداول

۱. چه موضوعات جاوایی را برای مصاحبه بخوانم؟

  • Core Java: مفاهیم OOP، تایپهای داده، عملگرها، ساختارهای کنترلی، متدها و مدیریت Exception.
  • فریم‌ورک Java Collections: List، Set، Map و Queue.
  • Multi-Thread و هم‌زمانی: ساخت Thread، Synchronization و Collectionهای هم‌زمان.
  • کتابخانه استاندارد جاوا: آشنایی با کلاسهایی مثل String، StringBuilder و Arrays.
  • بهترین روشهای جاوا: سازمان‌دهی کد، قراردادهای نام‌گذاری و استانداردهای کدنویسی.

۲. چطور برای مصاحبه فنی جاوا آماده شوم؟

  • مبانی را مرور کنید: مفاهیم Core جاوا، ساختارهای داده و الگوریتمها.
  • کدنویسی تمرین کنید: حل مسائل روی پلتفرمهایی مثل LeetCode، HackerRank یا CodeWars.
  • روی موضوعات رایج مصاحبه تمرکز کنید: Multi-Thread، هم‌زمانی و موضوعات خاص جاوا مثل Serialization و Reflection.
  • برای پاسخ به سوالات رفتاری آماده باشید: برای بحث پروژههای گذشته، تصمیمات طراحی و رویکردهای حل مسئله آماده باشید.
  • Whiteboarding تمرین کنید: تمرین توضیح مفاهیم فنی و طراحی سیستمها روی Whiteboard.

۳. روی چه نسخه‌ای از جاوا برای مصاحبه تمرکز کنم؟

برای مصاحبههای جاوا، تمرکز روی جاوا ۸ و قابلیتهایش—مانند عبارات Lambda، برنامه‌نویسی تابعی و API جدید تاریخ/زمان—توصیه می‌شود. اما دانستن جاوا ۱۱ و بهبودهایش هم مفید است.

۴. Multi-Thread در مصاحبههای جاوا چقدر مهم است؟

Multi-Thread موضوع حیاتی در مصابحهای جاواست—چون جنبه کلیدی برنامه‌نویسی جاواست. باید برای پاسخ به سوالات ساخت Thread، Synchronization، Deadlock و Collectionهای هم‌زمان آماده باشید. مفاهیم Multi-Thread اغلب برای ارزیابی توانایی نامزد در نوشتن کد کارآمد، مقیاس‌پذیر و امن-برای-Thread استفاده می‌شوند.

۵. چه مسائل کدنویسی جاوای خوبی برای تمرین وجود دارد؟

  • معکوس کردن رشته یا آرایه
  • یافتن عنصر وسط LinkedList
  • پیاده Stack با دو Queue
  • یافتن اولین مورد تکراری در آرایه
  • پیاده درخت جستجوی دودویی (BST)
  • حل مسئله Producer-Consumer با Multi-Thread
  • پیاده Cache با HashMap
  • یافتن حداکثر مجموع Subarray

نتیجه‌گیری

این مجموعه ۵۰ سوال برنامه‌نویسی جاوا—including سوالاتی از سطح مبتدی تا خبره—برای کمک به آمادگی مصاحبه‌تان بود.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا