-
تبدیل یک آرایه به ArrayList .
برای تبدیل یک آرایه به ArrayList ، توسعه دهندگان اغلب از این روش استفاده می کنند:
List<String> list = Arrays.asList(arr);
Arrays.asList()
یک شی کلاس را برمی گرداند کهArrayList
یک کلاس استاتیک خصوصی داخلی کلاس(private static class)
است ،Arrays
و این یک کلاس نیست . برای ایجاد یک واقعی ، این کار را انجام دهید:java.util.ArrayList.
java.util.Arrays.ArrayList
set()
get()
contains()
java.util.ArrayList
ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr));
سازنده کلاس
java.util.ArrayList
می تواند تمام اشیایی را که یک اینترفیس را پیاده سازی می کنند، به عنوان پارامتر انتخاب کندCollection
، پیاده سازی آن توسط کلاس به ارث برده می شود.java.util.Arrays.ArrayList
(کلاس استاتیک خصوصی ArrayList<E> AbstractList<E> RandomAccess را پیاده سازی می کند، java.io.Serializable).
-
بررسی یک آرایه برای یک مقدار خاص.
توسعه دهندگان اغلب این کار را انجام می دهند:
Set<String> set = new HashSet<String>(Arrays.asList(arr)); return set.contains(targetValue);
کد کار می کند، اما نیازی به تبدیل آن
List
بهSet
. تبدیل بهSet
زمان بیشتری نیاز دارد. در واقع همه چیز ساده است:Arrays.asList(arr).contains(targetValue);
یا
for(String s: arr){ if(s.equals(targetValue)) return true; } return false;
روش اول بسیار کوتاهتر است.
-
حذف یک عنصر از
List
یک حلقهکد زیر را در نظر بگیرید که عناصر یک حلقه را حذف می کند:
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d")); for (int i = 0; i < list.size(); i++) { list.remove(i); } System.out.println(list);
نتیجه:
[b, d]
معلوم می شود که این یک اشتباه جدی است. هنگامی که یک عنصر حذف می شود، اندازه
List
کاهش می یابد و شاخص های عنصر تغییر می کند.بنابراین اگر می خواهید چندین عنصر را در یک حلقه با استفاده از یک شاخص حذف کنید، از این روش اجتناب کنید.
ممکن است بدانید که استفاده از تکرار کننده راه حل صحیح برای حذف عناصر در یک حلقه است، و می دانید که یک حلقه سبک
for-each
مانند یک تکرار کننده عمل می کند، اما اینطور نیست.کد زیر را در نظر بگیرید:
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d")); for (String s : list) { if (s.equals("a")) list.remove(s); }
ما یک ConcurrentModificationException دریافت خواهیم کرد .
کار درست این است:
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d")); Iterator<String> iter = list.iterator(); while (iter.hasNext()) { String s = iter.next(); if (s.equals("a")) { iter.remove(); } }
متد
در یک Loop-stylenext()
باید قبل از فراخوانی شودremove()
.for-each
، کامپایلر متد را فراخوانی میکندremove()
و تنها پس از آنnext()
، یک خطا ایجاد میکندConcurrentModificationException
. می توانید به کد نگاه کنیدArrayList.iterator()
. -
Hashtable
در برابرHashMap
.با توجه به پیاده سازی مربوطه، Hashtable نام ساختار داده است.
اما در جاوا نام ساختار داده است
HashMap
. یکی از تفاوت های کلیدی بینHashtable
و همگام بودنHashMap
آن استHashtable
بنابراین نبایدHashtable
در جایی استفاده شودHashMap
.HashMap در مقابل نقشه درختی در مقابل Hashtable در مقابل LinkedHashMap .
-
از مجموعه ها بدون محدودیت محتوا استفاده کنید
В Java часто путают коллекции без ограничений по содержимому, и коллекции с маской по типу содержимого. К примеру, для множеств -
Set
это коллекция без ограничений по содержимому, аSet<?>
— коллекция у которой все-таки есть ограничения, но эти ограничения ничего на самом деле не ограничивают. Рассмотрим следующий code, гдеList
без ограничений используется в качестве параметра метода:public static void add(List list, Object o){ list.add(o); } public static void main(String[] args){ List<String> list = new ArrayList<String>(); add(list, 10); String s = list.get(0); }
Данный code выбросит исключение:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at …
Использование коллекций без ограничений по содержимому очень опасно, потому что вы не можете быть уверенными в том что там лежит внутри. А для того чтобы понять всю глубину разницы между
Set
,Set<?>
иSet<Object>
— почитайте вот эту и эту ссылки. -
Уровень доступа
Очень часто для полей класса разработчики используют модификатор доступа
public
. Так проще получить meaning поля напрямую. Правильнее использовать How можно более ограниченный доступ к членам класса. ArrayList
противLinkedList
Когда разработчики не знают чем отличается
ArrayList
отLinkedList
, они используют первый в силу его большей известности. Однако, есть огромная разница в производительности между ними. На самом деле, выбор между ними должен быть продиктован их внутренними особенностями —ArrayList
позволяет быстро производить доступ к произвольному элементу массива, аLinkedList
— быстро добавлять/удалять элементы в массиве. Почитайте статью по ссылке ArrayList vs. LinkedList чтобы понять причины их разной производительности.Mutable
(Изменяемый) противImmutable
(Неизменяемый)Неизменяемый an object имеет много преимуществ: простота, безопасность и т.д. Но он требует отдельного an object для каждого нового значения, и за слишком большое количество an objectов придется заплатить понижением производительности. Должен быть баланс при выборе между изменяемым и неизменяемым обьектом.
В основном чтобы избежать подготовки промежуточных an objectов используется изменяемый an object. Один из классических примеров это конкатенация большого количества строк. Если вы используете неизменяемый an object типа
String
, то вы создаете много an objectов, которые сразу попадут в сборщик мусора. Это тратит время и энергию процессора, поэтому правильное решение это использование изменяемых обьектов (напримерStringBuilder
).String result=""; for(String s: arr){ result = result + s; }
Еще один пример использования изменяемых an objectов — передача такого an object в метод. Это позволит вернуть результат в нем же, без создания лишних an objectов. При работе с an objectми большого размера, к примеру коллекциями, передача коллекции в метод для сортировки и возвращение результата в другой коллекции приводит к совершенно излишнему расходу ресурсов. (Ответ пользователя dasblinkenlight на Stack Overflow).
-
Конструкторы классов
Super
иSub
این خطای کامپایل به دلیل این واقعیت است که کلاس ancestor سازنده پیش فرض تعریف شده ندارد. در جاوا ، مگر اینکه خودتان سازنده کلاس را مشخص کنید، کامپایلر سازنده پیش فرضی ایجاد می کند که به آرگومان نیاز ندارد. اگر سازنده در کلاس
Super
به صورت توضیح داده شودSuper(String s){}
، خود کامپایلر چیزی اضافه نخواهد کرد. این چیزی است که در مثال خود می بینیم.سازنده کلاس
Sub
، مهم نیست که کدام یک، سازنده پیش فرض کلاس را فراخوانی می کندSuper
، زیرا چیز دیگری مشخص نشده است. از آنجایی که هیچ سازنده پیش فرضی در کلاس وجود نداردSuper
، این منجر به یک خطای کامپایل می شود.اولین راه حل برای این مشکل اضافه کردن یک سازنده پیش فرض به کلاس است
Super
public Super(){ System.out.println("Super"); }
گزینه دوم این است که سازنده ای را که توضیح دادیم از کلاس حذف کنیم
Super
تا کامپایلر یک سازنده پیش فرض ایجاد کند.و آخرین گزینه این است که یک فراخوانی
super(value)
به سازنده های کلاس اضافه کنیدSub
تا سازنده کلاس موجود به جای سازنده پیش فرض فراخوانی شود.Super
-
"" یا سازنده؟
دو راه برای ایجاد رشته وجود دارد:
//1. использовать двойные кавычки String x = "abc";
//2. использовать конструктор String y = new String("abc");
چه تفاوتی بین آنها وجود دارد؟
این را می توانید از مثال های زیر درک کنید:
String a = "abcd"; String b = "abcd"; System.out.println(a == b); // True System.out.println(a.equals(b)); // True String c = new String("abcd"); String d = new String("abcd"); System.out.println(c == d); // False System.out.println(c.equals(d)); // True
برای کسب اطلاعات بیشتر در مورد نحوه ذخیره رشته ها در حافظه، ایجاد رشته جاوا با استفاده از "" یا سازنده را بخوانید؟ .
GO TO FULL VERSION