50 پرسش و پاسخ اصلی مصاحبه اصلی جاوا. قسمت 1
مجموعه ها
25. منظور از مجموعه در جاوا چیست؟
مجموعه چارچوبی است که برای ذخیره و دستکاری اشیا طراحی شده است. برای انجام عملیات زیر استفاده می شود:- جستجو کردن؛
- مرتب سازی؛
- دستکاری - اعمال نفوذ؛
- اضافه شدن
- حذف
java.util
بسته موجود است.
26. چه کلاس ها و رابط هایی در چارچوب مجموعه موجود است؟
رابط ها:- مجموعه؛
- فهرست؛
- تنظیم؛
- نقشه;
- مجموعه مرتب شده
- نقشه مرتب شده؛
- صف
- لیست ها:
- ArrayList;
- LinkedList;
- وکتور (منسوخ شده).
- مجموعه ها:
- هش ست؛
- LinkedHashSet;
- مجموعه درختی.
- نقشه ها:
- HashMap
- نقشه درختی
- HashTable (منسوخ شده)
- LinkedHashMap
- صف
- صف اولویت.
27. منظور از مرتب و مرتب شده در مجموعه ها چیست؟
سفارش داده شده:
این بدان معنی است که مواردی که در مجموعه ذخیره می شوند بر اساس مقادیر اضافه شده به مجموعه هستند. به این ترتیب میتوانیم مقادیر را از مجموعه به ترتیب خاصی تکرار کنیم. به عبارت دیگر، این بدان معناست که عناصر مجموعه، ترتیب خاص خود را دارند که بر اساس آن چیده شده اند. برای درک بهتر، مجموعه ای که سفارش داده نشده است، عناصر خود را به صورت تصادفی ذخیره می کند. به عنوان مثال، Set.مرتب شده:
این بدان معنی است که گروهی از عناصر بر اساس داده های عنصر مجموعه در یک مجموعه طبقه بندی می شوند. یعنی نه تنها مجموعه مرتب است، بلکه ترتیب عناصر نیز به مقادیر آنها بستگی دارد. اگر بر اساس مقدار عنصر دیگری مرتب کنید، این ترتیب ممکن است تغییر کند.28. چه مجموعه هایی با رابط List وجود دارد؟ چگونه با لیست کار می کنید؟
مقادیر عناصر در یک صفحه بر اساس شاخص آنها است - آنها بر اساس شاخص مرتب می شوند. تکرار عناصر مجاز است (یعنی می توانید یک شیء مشابه را چندین بار به مجموعه اضافه کنید و خوب می شود).ArrayList:
رایج ترین مجموعه. در اصل، آرایه ای با اندازه پویا در حال گسترش است. کار مدیریت اندازه آرایه بر عهده مجموعه است. درک این نکته برای ما مهم است که در بیشتر موارد این همان چیزی است که باید استفاده کنیم. ویژگی ها:- جستجوی سریع و جستجوی سریع فهرست؛
- مجموعه بر اساس فهرست مرتب شده است، اما مرتب نشده است.
- رابط RandomAccess را پیاده سازی می کند.
- کم کم به وسط لیست اضافه می شود.
public class A {
public static void main(String[] args) {
ArrayList names = new ArrayList<>();
names.add("John");
names.add("John");
names.add("Roman");
names.add("Ivan");
}
}
>> خروجی
[John, John, Roman, Ivan]
خروجی نشان می دهد که این عناصر تکرارپذیر هستند. آنها به ترتیبی که ضبط شده اند نمایش داده می شوند. چه چیز دیگری برای خواندن؟ بله، اطلاعات زیادی وجود دارد، شما حتی نیازی به ترک JavaRush ندارید:
لیست پیوندی:
این مجموعه ای است که در آن هر عنصر پیوندی به عناصر قبلی و بعدی دارد. این پیوندها به شما امکان می دهند از یک عنصر به عنصر دیگر بروید. هنگام اضافه کردن یک عنصر، پیوندهای عناصر قبلی و بعدی به سادگی تغییر می کنند:- عناصر به یکدیگر متصل می شوند، یعنی یک لیست پیوندی دوگانه پیاده سازی می شود.
- سرعت کلی عملیات به طور قابل توجهی کمتر از ArrayList است.
- یک انتخاب عالی برای تعداد زیادی درج و حذف در وسط یک آرایه.
- رابط های لیست Queue و Deque را پیاده سازی می کند و بنابراین روش های خود را برای کار دارد.
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("One");
linkedList.add("Two");
linkedList.add("Three");
29. در مورد مجموعه نقشه و پیاده سازی های آن بگویید؟
نقشه یک مجموعه کلید-مقدار است. یک کلید منحصر به فرد و مقداری وجود دارد که با آن مقدار مطابقت دارد.equals()
همچنین از روش هایی hashcode()
برای تعیین منحصر به فرد بودن یک کلید استفاده می شود.
HashMap:
- مرتب یا مرتب نشده است.
- اگر ترتیب و مرتب سازی مهم نباشد استفاده می شود.
- از کلید تهی پشتیبانی می کند.
public class CollectionExample {
public static void main(String[] args) {
HashMap positions = new HashMap<>();
positions.put("junior", "Ivan");
positions.put("middle", "Roman");
positions.put("senior", "Vasily");
positions.put("team lead", "Anton");
positions.put("arthitect", "Andrew");
positions.put("senior", "John");
System.out.println(positions);
}
}
// вывод в консоль
// {junior=Ivan, middle=Roman, senior=John, team lead=Anton, arthitect=Andrew}
کلیدها همیشه منحصر به فرد هستند، بنابراین فقط یک ارشد ثبت می شود.
LinkedHashMap:
- نظم درج را حفظ می کند.
- کندتر از HashMap؛
- انتظار می رود که تکرار سریعتر از HashMap باشد.
public class CollectionExample {
public static void main(String[] args) {
LinkedHashMap<String, String> positions = new LinkedHashMap<>();
positions.put("junior", "Ivan");
positions.put("middle", "Roman");
positions.put("senior", "Vasily");
positions.put("team lead", "Anton");
positions.put("arthitect", "Andrew");
positions.put("senior", "John");
System.out.println(positions);
}
}
// вывод в консоль
// {junior=Ivan, middle=Roman, senior=John, team lead=Anton, arthitect=Andrew}
نقشه درختی:
پیادهسازی نقشه که ورودیها را بر اساس ترتیب طبیعی کلیدهایشان مرتب میکند، یا بهتر است بگوییم با استفاده از مقایسهکنندهای که در سازنده هنگام ایجاد نقشه وجود دارد. مثال:-
بدون مقایسه
public class CollectionExample { public static void main(String[] args) { TreeMap<Integer, String> positions = new TreeMap<>(); positions.put(1, "Ivan"); positions.put(3, "Roman"); positions.put(2, "Vasily"); positions.put(10, "Anton"); positions.put(7, "Andrew"); positions.put(1, "John"); System.out.println(positions); } } // вывод в консоль // {1=John, 2=Vasily, 3=Roman, 7=Andrew, 10=Anton}
-
با مقایسه کننده
public class CollectionExample { public static void main(String[] args) { //используем реализацию Strategy Pattern'a и добавим компаратор: TreeMap<Integer, String> positions = new TreeMap<>(Comparator.reverseOrder()); positions.put(1, "Ivan"); positions.put(3, "Roman"); positions.put(2, "Vasily"); positions.put(10, "Anton"); positions.put(7, "Andrew"); positions.put(1, "John"); System.out.println(positions); } } // вывод в консоль // {10=Anton, 7=Andrew, 3=Roman, 2=Vasily, 1=John}
30. درباره مجموعه ست و پیاده سازی های آن بگویید؟
مجموعه مجموعه ای از عناصر منحصر به فرد است و این ویژگی اصلی آن است. یعنی Set اجازه تکرار همان عناصر را نمی دهد. در اینجا مهم است که اشیاء اضافه شده دارای یک متد پیاده سازی شده باشندequals
.
HashSet:
- مرتب یا مرتب نشده است در زیر هود یک HashMap با یک مکان نگهدار برای مقدار وجود دارد. خودت ببین ؛)
- از هش کد برای اضافه کردن اشیا استفاده می کند.
- زمانی که نیاز به داشتن اشیاء منحصر به فرد دارید و ترتیب آنها مهم نیست باید از آن استفاده کنید.
public class CollectionExample {
public static void main(String[] args) {
HashSet<String> positions = new HashSet<>();
positions.add("junior");
positions.add("junior");
positions.add("middle");
positions.add("senior");
positions.add("team lead");
positions.add("architect");
System.out.println(positions);
}
}
// вывод в консоль
// [senior, middle, team lead, architect, junior]
در اینجا می توانید ببینید که عنصر "junior" که دو بار اضافه شده است، فقط در یک نمونه وجود دارد. و ترتیب مانند هنگام اضافه کردن نیست.
LinkedHashSet:
- نسخه سفارش داده شده HashSet؛
- یک لیست با پیوند دوگانه برای همه عناصر حفظ می کند.
- زمانی که در تکرار خود به نظم نیاز دارید از آن استفاده کنید.
public class CollectionExample {
public static void main(String[] args) {
LinkedHashSet<String> positions = new LinkedHashSet<>();
positions.add("junior");
positions.add("junior");
positions.add("middle");
positions.add("senior");
positions.add("team lead");
positions.add("architect");
System.out.println(positions);
}
}
// вывод в консоль
// [senior, middle, team lead, architect, junior]
مجموعه درختی:
- یکی از دو مجموعه مرتب شده؛
- از ساختار درختی قرمز-مشکی استفاده می کند و اطمینان می دهد که عناصر به ترتیب صعودی هستند.
- زیر کاپوت آن یک TreeMap با یک خرد روی مقادیر است. و عناصر TreeSet کلیدهای TreeMap هستند (همچنین به ;) مراجعه کنید.
public class CollectionExample {
public static void main(String[] args) {
TreeSet<String> positions = new TreeSet<>();
positions.add("junior");
positions.add("junior");
positions.add("middle");
positions.add("senior");
positions.add("team lead");
positions.add("architect");
System.out.println(positions);
}
}
// вывод в консоль
// [architect, junior, middle, senior, team lead]
استثناها
31. استثنا چیست؟
استثنا مشکلی است که می تواند در زمان اجرا رخ دهد. این یک وضعیت استثنایی است که به دلایلی ایجاد می شود. نمودار وراثت استثنا به این شکل است (شما باید آن را از روی قلب بدانید ؛)): نمودار نشان می دهد که به طور کلی، همه استثناها به دو گروه تقسیم می شوند - استثنا و خطا. خطا - JVM ها برای نمایش خطاها استفاده می شوند که پس از آن برنامه دیگر معنی ندارد. به عنوان مثال StackOverFlowError که می گوید پشته پر است و برنامه دیگر نمی تواند اجرا شود. استثنا - استثناهایی که به صورت برنامه نویسی در کد ایجاد می شوند. استثناهای مختلفی وجود دارد، بررسی شده و بدون علامت، اما نکته اصلی این است که آنها وجود دارند و می توان آنها را گرفت و برنامه به کار خود ادامه می دهد. استثناها نیز به نوبه خود به مواردی تقسیم می شوند که از RuntimeException و دیگر فرزندان Exception به ارث می برند. اطلاعات کافی در مورد این موضوع وجود دارد. در زیر در مورد مواردی که استثناهای علامت زده/بدون علامت هستند صحبت خواهیم کرد.32. چگونه JVM استثناها را مدیریت می کند؟
چگونه کار می کند؟ به محض اینکه یک استثنا در جایی پرتاب شود، زمان اجرا یک Object Exception (که با ExcObj مشخص می شود) ایجاد می کند. تمام اطلاعات لازم برای کار را ذخیره می کند - خود استثنایی که پرتاب شده است و مکانی که در آن اتفاق افتاده است. ایجادExcObj
و انتقال به زمان اجرا چیزی بیش از "پرتاب یک استثنا" نیست. ExcObj
حاوی روش هایی است که می توان از آنها برای رسیدن به جایی که استثنا پرتاب شده است استفاده کرد. این مجموعه از روش ها Call Stack نامیده می شود. در مرحله بعد، سیستم زمان اجرا به دنبال روشی در Call Stack می گردد که بتواند استثنای ما را مدیریت کند. اگر کنترل کننده مناسب را پیدا کند، یعنی نوع استثنا با نوع کنترل کننده مطابقت داشته باشد، همه چیز خوب است. اگر آن را پیدا نکرد، زمان اجرا همه چیز را به کنترل کننده استثنای پیشفرض منتقل میکند، که پاسخی را آماده میکند و خارج میشود. این چیزی است که به نظر می رسد:
/**
* Пример, в котором показываются две опции — когда находится обработчик для исключения и когда нет.
*/
class ThrowerExceptionExample {
public static void main(String[] args) throws IllegalAccessException {
ThrowerExceptionExample example = new ThrowerExceptionExample();
System.out.println(example.populateString());
}
/**
* Здесь происходит перехват одного из возможных исключений — {@link IOException}.
* А вот второй будет пробрасываться дальше вверх по вызову.
*/
private String populateString() throws IllegalAccessException {
try {
return randomThrower();
} catch (IOException e) {
return "Caught IOException";
}
}
/**
* Здесь две опции: or бросается {@link IOException} or {@link IllegalAccessException}.
* Выбирается случайным образом.
*/
private String randomThrower() throws IOException, IllegalAccessException {
if (new Random().nextBoolean()) {
throw new IOException();
} else {
throw new IllegalAccessException();
}
}
}
در مورد ما، CallStack به صورت شماتیک به نظر می رسد:
randomThrower() => populateString() => main(String[] args)
دو گزینه وجود دارد: یکی یا دیگری استثنا به طور تصادفی پرتاب می شود. برای IOException همه چیز اوکی است، اگر تولید شود، نتیجه کار این خواهد بود: "Caught IOException"
. اما اگر استثنای دومی وجود داشته باشد که کنترل کننده ای برای آن وجود نداشته باشد، برنامه با خروجی زیر متوقف می شود:
Exception in thread "main" java.lang.IllegalAccessException
at ThrowerExceptionExample.randomThrower(CollectionExample.java:38)
at ThrowerExceptionExample.populateString(CollectionExample.java:24)
at ThrowerExceptionExample.main(CollectionExample.java:15)
33. برنامه نویسان چگونه استثناها را مدیریت می کنند؟
در سؤالات بالا، قبلاً از کلمات کلیدی خاصی برای کار با استثناها استفاده شده است؛ اکنون باید در مورد آنها با جزئیات بیشتری صحبت کنیم. کلمات کلیدی چیست؟- تلاش كردن
- گرفتن
- پرت كردن
- پرتاب می کند
- سرانجام
try-catch-finally
ساختاری است که به شما امکان می دهد استثنا را به درستی دریافت و مدیریت کنید.try
- فقط یک بار می تواند وجود داشته باشد، اینجاست که منطق اتفاق می افتد.catch
- بلوکی که نوعی استثنا را دریافت میکند؛ میتواند تعداد زیادی از آنها وجود داشته باشد. به عنوان مثال، یک بلوک try چندین استثنا ایجاد می کند که هیچ ارتباطی با یکدیگر ندارند.finally
- "بالاخره" این بلوک. این بلوکی است که در هر صورت، صرف نظر از آنچه در try, catch انجام می شود، اجرا می شود.
try {
// сюда передают тот code, который может вызвать исключение.
} catch (IOException e) {
// первый catch блок, который принимает IOException и все его подтипы(потомки).
// Например, нет file при чтении, выпадает FileNotFoundException, и мы уже соответствующе
// обрабатываем это.
} catch (IllegalAccessException e) {
// если нужно, можно добавить больше одного catch блока, в этом нет проблем.
} catch (OneException | TwoException e) {
// можно даже объединять несколько в один блок
} catch (Throwable t) {
// а можно сказать, что мы принимаем ВСЁ))))
} finally {
// этот блок может быть, а может и не быть.
// и он точно выполнится.
}
توضیحات مثال را با دقت بخوانید و همه چیز روشن خواهد شد)
34. پرتاب و پرتاب در جاوا
پرت كردن
throw
زمانی استفاده می شود که نیاز به ایجاد یک استثنا جدید دارید. برای ایجاد و پرتاب استثناهای سفارشی استفاده می شود. به عنوان مثال، استثناهای مربوط به اعتبارسنجی. معمولاً برای اعتبار سنجی، از RuntimeException
. مثال:
// пример пробрасывания исключения
throw new RuntimeException("because I can :D");
مهم است که این ساخت و ساز فقط می تواند توسط چیزی که از آن به ارث می رسد استفاده شود Throwable
. یعنی شما نمی توانید این را بگویید:
throw new String("How тебе такое, Илон Маск?");
در مرحله بعد، کار رشته پایان می یابد و جستجو برای کنترل کننده ای که بتواند آن را پردازش کند آغاز می شود. هنگامی که آن را پیدا نمی کند، به روشی که آن را فراخوانی کرده است می رود، و بنابراین جستجو در خط تماس ها بالا می رود تا زمانی که کنترل کننده مربوطه را پیدا کند یا برنامه را در حال اجرا رها کند. بیایید نگاه بیندازیم:
// Пример, который демонстрирует работу throw
class ThrowExample {
void willThrow() throws IOException {
throw new IOException("Because I Can!");
}
void doSomething() {
System.out.println("Doing something");
try {
willThrow();
} catch (IOException e) {
System.out.println("IOException was successfully handled.");
}
}
public static void main(String args[]) {
ThrowExample throwExample = new ThrowExample();
throwExample.doSomething();
}
}
اگر برنامه را اجرا کنیم به نتیجه زیر می رسیم:
Doing something
IOException was successfully handled.
پرتاب می کند
throws
- مکانیزمی که توسط آن یک روش می تواند یک یا چند استثنا ایجاد کند. آنها با کاما از هم جدا می شوند. بیایید ببینیم چقدر آسان و ساده است:
private Object willThrow() throws RuntimeException, IOException, FileNotFoundException
علاوه بر این، توجه به این نکته مهم است که هم میتوان استثناهای علامتدار و بدون علامت وجود داشته باشد. البته ممکن است استثنائات علامت نخورده به اضافه نشود throws
، اما اخلاق خوب چیز دیگری می گوید. اگر اینها قابل بررسی هستند، پس با استفاده از روشی که آنها را تولید می کند، باید به نحوی آن را پردازش کنید. دو گزینه وجود دارد:
try-catch
با استثناء ارثی مناسب و فوق بنویسید .- دقیقاً به همین شکل از آن استفاده کنید
throws
تا شخص دیگری قبلاً این مشکل را داشته باشد :D
35. استثناهای چک شده و بدون علامت در جاوا
دو نوع استثنا در جاوا وجود دارد - چک شده و بدون علامت.استثناهای بررسی شده:
اینها استثناهایی هستند که در زمان کامپایل بررسی می شوند. اگر برخی از کدهای یک متد یک استثنای علامت زده را در طول یک استثنا پرتاب کند، متد باید یا آن را با استفاده از آن مدیریت کندtry-catch
، یا آن را بیشتر ارسال کند. به عنوان مثال، که تصویری را از مسیر "/users/romankh3/image.png" می خواند، آن را به روز می کند. به نحوی (برای ما این مهم نیست) و آن را پس انداز می کند.
class CheckedImageExample {
public static void main(String[] args) {
File imageFile = new File("/users/romankh3/image.png");
BufferedImage image = ImageIO.read(imageFile);
updateAndSaveImage(image, imageFile);
}
private static void updateAndSaveImage(BufferedImage image, File imageFile) {
ImageIO.write(image, "png", imageFile);
}
}
چنین کدی کامپایل نمیشود، زیرا روشهای استاتیک یک IOException را ImageIO.read()
پرتاب میکنند ImageIO.write()
، که بررسی میشود و باید بر اساس آن مدیریت شود. در اینجا دو گزینه وجود دارد که قبلاً در بالا مورد بحث قرار گرفتهایم: یا استفاده کنید try-catch
، یا بیشتر بفرستید. برای جذب بهتر، این و آن را انجام می دهیم. یعنی updateAndSave
فقط آن را در متد فوروارد می کنیم و سپس از آن در متد اصلی استفاده می کنیم try-catch
:
class CheckedImageExample {
public static void main(String[] args) {
File imageFile = new File("/users/romankh3/image.png");
try {
BufferedImage image = ImageIO.read(imageFile);
updateAndSaveImage(image, imageFile);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void updateAndSaveImage(BufferedImage image, File imageFile) throws IOException {
ImageIO.write(image, "png", imageFile);
}
}
استثناهای بدون علامت:
اینها استثناهایی هستند که در مرحله تدوین بررسی نمی شوند. یعنی یک متد می تواند RuntimeException ایجاد کند، اما کامپایلر به شما یادآوری نمی کند که به نحوی آن را مدیریت کنید. همانطور که در زیر نشان داده شده است، همه چیزهایی که از RuntimeException و Error به ارث می رسد بدون تیک وجود دارد. برنامه جاوا زیر را در نظر بگیرید. کد به خوبی کامپایل می شود، اما هنگام اجرا یک استثنا ایجاد می کندArrayIndexOutOfBoundsException
. کامپایلر به آن اجازه می دهد تا کامپایل شود زیرا ArrayIndexOutOfBoundsException
یک استثناء بدون علامت است. یک موقعیت رایج با یک آرایه، که می تواند:
class CheckedImageExample {
public static void main(String[] args) {
int[] array = new int[3];
array[5] = 12;
}
}
نتیجه این خواهد بود:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at main(CheckedImageExample.java:12)
به هر حال، آیا قبلاً متوجه شده اید که در جاوا هیچ کس نام کوتاه نمی گذارد؟ هرچه بزرگتر بهتر. او، Spring Framework، در این امر بسیار موفق بود: فقط کافی است در کلاس BeanFactoryPostProcessor شرکت کنید )))
36. try-with-sources چیست؟
این مکانیزمی است که توسط آن همه منابع باید به درستی بسته شوند. به نوعی مشخص نیست، درست است؟) اول از همه، منبع چیست... منبع یک شی است که پس از کار با آن باید آن را ببندید، یعنی با شماره تماس بگیریدclose()
. یک منبع تمام اشیایی است که یک رابط را پیاده سازی می کند AutoClosable
، که به نوبه خود یک رابط را پیاده سازی می کند Closeable
. برای ما مهم است که بفهمیم همه چیز یک منبع InputStream
است OutpuStream
و باید به درستی و با موفقیت منتشر شود. دقیقاً به همین دلیل است که باید از try-with-resource
ساختار استفاده کنیم. در اینجا به نظر می رسد:
private void unzipFile(File zipFile) throws IOException {
try(ZipInputStream zipOutputStream = new ZipInputStream(new FileInputStream(zipFile))) {
ZipEntry zipEntry = zipOutputStream.getNextEntry();
while (zipEntry != null) {
}
}
}
private void saveZipEntry(ZipEntry zipEntry) {
// логика сохранения
}
در این مثال، منبعی است ZipInputStream
که پس از کار با آن باید آن را ببندید. و برای اینکه به فراخوانی متد فکر نکنیم close()
، همانطور که در مثال نشان داده شده است، به سادگی این متغیر را در یک بلوک try تعریف می کنیم، و در داخل این بلوک همه کارهای لازم را انجام می دهیم. مثال چه کار می کند؟ بایگانی فشرده را از حالت فشرده خارج می کند. برای این کار باید InputStream
از om استفاده کنید. شما می توانید بیش از یک متغیر تعریف کنید؛ آنها با یک نقطه ویرگول از هم جدا می شوند. مشکل چیست؟ finally
اما ممکن است بگویید می توانید از یک بلوک استفاده کنید . در اینجا مقاله ای وجود دارد که به جزئیات مشکلات این رویکرد می پردازد. همچنین فهرست کاملی از شکستهایی را که ممکن است برای کسی که از استفاده از این طرح غفلت میکند رخ دهد، توضیح میدهد. خواندن آن را توصیه می کنم ؛) در قسمت پایانی سؤالات / پاسخ هایی در مورد موضوع Multithreading وجود دارد. پروفایل GitHub من
GO TO FULL VERSION