تتركز المجموعات في Java بشكل أساسي في جزأين، أحدهما موجود في الحزمة java.util والآخر في java.util.concurrent، ويستند الأخير إلى الأول ويحدد بعض المجموعات التي تنفذ وظائف المزامنة.
تركز هذه المقالة بشكل أساسي على كائنات المجموعة المتنوعة ضمن java.util. يمكن تقسيم كائنات المجموعة في Java تقريبًا إلى ثلاث فئات: القائمة، والضبط، والخريطة. مخطط UML المقابل هو كما يلي (بما في ذلك معظم كائنات المجموعة ضمن java.util):
نظرة عامة على المجموعة
تأتي كل من مجموعات List وSet في Java من Collection، وهي نقطة دخول جيدة لمجموعات التعلم، وتتضمن العمليات المطلوبة عادةً في المجموعات:
إضافة عناصر: إضافة/إضافة الكل
مسح المجموعة: واضح
إزالة العناصر: إزالة/إزالة الكل
تحديد ما إذا كانت المجموعة تحتوي على عنصر: يحتوي على/يحتوي على الكل
تحديد ما إذا كانت المجموعة فارغة: isEmpty
احسب عدد العناصر في المجموعة: الحجم
تحويل مجموعة إلى مصفوفة: toArray
الحصول على المكرر: المكرر
دعونا نلقي نظرة على مثال بسيط، الكود التالي سوف يُرجع مجموعة عناصرها عبارة عن أعداد صحيحة تم إنشاؤها بشكل عشوائي:
جمع العودة
}
1) استخدم التكرارات لاجتياز المجموعة. كما ذكرنا عند وصف واجهة المجموعة أعلاه، ستحتوي جميع المجموعات على مكرر يمكننا استخدامه لاجتياز المجموعة.
تعد القائمة في Java امتدادًا فعالاً للمصفوفة، وهي عبارة عن بنية يمكنها الاحتفاظ بعناصر من أي نوع إذا لم يتم استخدام الأدوية العامة، فيمكنها الاحتفاظ فقط بعناصر من النوع المحدد بواسطة الأدوية العامة. بالمقارنة مع المصفوفات، يمكن توسيع سعة القائمة ديناميكيًا.
يمكن تكرار العناصر الموجودة في القائمة، والعناصر الموجودة بداخلها "مرتبة". "مرتبة" هنا لا تعني الفرز، ولكنها تعني أنه يمكننا تحديد موضع العنصر في المجموعة.
تتضمن كائنات المجموعة شائعة الاستخدام في القائمة: ArrayList وVector وLinkedList، ويتم تخزين الاثنين السابقين على أساس المصفوفات، ويتم تخزين الأخير على أساس القوائم المرتبطة. من بينها، Vector آمن للخيط، والاثنان الآخران ليسا آمنين للخيط.
يمكن أن تحتوي القائمة على قيمة فارغة، حتى إذا تم استخدام الأدوية العامة.
قد يكون ArrayList هو كائن المجموعة الأكثر استخدامًا في كود المثال أعلاه، ونحن نستخدمه أيضًا لإنشاء كائن Collection، لذلك لن ندخل في التفاصيل هنا.
ناقل
مثال على Vector هو كما يلي أولاً ننظر إلى كيفية إنشاء وإخراج Vector:
[9، 29، 32، 54، 12]
حجم المتجه هو 3
[29، 32، 54]
يستخدم LinkedList القوائم المرتبطة لتخزين البيانات، ويكون نموذج التعليمات البرمجية الخاص به كما يلي:
الإخراج هو كما يلي:
باطل
باطل
باطل
حجم القائمة المرتبطة هو 8
[100، 84، 19، 57، 68، 26، 27، 47]
المجموعة تشبه القائمة، وكلاهما يستخدم لتخزين عنصر واحد، وعدد العناصر الفردية غير مؤكد. لكن لا يمكن أن تحتوي المجموعة على عناصر مكررة. إذا تم إدراج عنصرين متطابقين في المجموعة، فلن يتم إدراج العنصر الأخير.
يمكن تقسيم المجموعة تقريبًا إلى فئتين: المجموعة غير المصنفة والمجموعة المصنفة تتضمن HashSet وLinkedHashSet، وتشير المجموعة المصنفة بشكل أساسي إلى TreeSet. من بينها، يمكن أن تحتوي HashSet وLinkedHashSet على قيمة فارغة.
HashSet
HashSet عبارة عن مجموعة مدعومة بجدول Hash، وهي ليست آمنة لمؤشرات الترابط.
دعونا نلقي نظرة على المثال التالي، والذي هو في الأساس نفس المثال الأول مع Vector:
لـ (int i = 0; i < 3; i++)
{
set.add(new Integer(100));
}
set.add(null);
System.out.println("حجم المجموعة هو" + set.size());
System.out.println(set);
}
classMyInteger
{
قيمة عددية خاصة؛
MyInteger العام (قيمة عددية)
{
this.value = value;
}
سلسلة عامة إلى سلسلة ()
{
إرجاع String.valueOf(value);
}
رمز التجزئة العام ()
{
العودة 1؛
}
القيمة المنطقية العامة تساوي (Object obj)
{
عودة صحيحة؛
}
}
وفيما يلي طريقة الاختبار المقابلة:
لـ (int i = 0; i < 3; i++)
{
set.add(new MyInteger(100));
}
System.out.println("حجم المجموعة هو" + set.size());
System.out.println(set);
}
TreeSet عبارة عن مجموعة تدعم الفرز، والواجهة الرئيسية الخاصة بها هي SortedSet.
دعونا أولاً نلقي نظرة على العمليات الأساسية لـ TreeSet:
Random r = new Random();
لـ (int i = 0; i < 5; i++)
{
set.add(new Integer(r.nextInt(100)));
}
System.out.println(set);
System.out.println(set.first());
System.out.println(set.last());
System.out.println(set.descendingSet());
System.out.println(set.headSet(new Integer(50)));
System.out.println(set.tailSet(new Integer(50)));
System.out.println(set.subSet(30, 60));
System.out.println(set.floor(50));
System.out.println(set.ceiling(50));
}
[53، 49، 48، 42، 8]
[8، 42، 48، 49]
[53]
[42، 48، 49، 53]
بعد ذلك، نقوم أولاً بإعادة تعريف العدد الصحيح:
MyInteger2 العامة (قيمة int)
{
this.value = value;
}
int العام قارن إلى (كائن arg0)
{
MyInteger2 temp = (MyInteger2)arg0;
إذا (درجة الحرارة == فارغة) العودة -1؛
إذا (قيمة مؤقتة > هذه القيمة)
{
العودة 1؛
}
وإلا إذا (قيمة مؤقتة < هذه. قيمة)
{
العودة -1؛
}
العودة 0؛
}
القيمة المنطقية العامة تساوي (Object obj)
{
إرجاع CompareTo(obj) == 0;
}
سلسلة عامة إلى سلسلة ()
{
إرجاع String.valueOf(value);
}
}
تخزن الخرائط "أزواج القيمة الرئيسية". على غرار Set، يوجد نوعان من الخرائط في Java: الخرائط المصنفة وغير المصنفة والتي تتضمن HashMap وHashtable وLinkedHashMap، وتتضمن الخرائط المصنفة TreeMap.
خريطة غير مصنفة
يتم تخزين كل من HashMap وHashtable في شكل جداول Hash. HashMap ليس آمنًا لمؤشر الترابط، ولكن يمكننا اعتبار HashMap بمثابة نسخة "مبسطة" من Hashtable.
يمكن لـ HashMap تخزين قيمة فارغة، سواء للمفتاح أو القيمة. لا يمكن تخزين Hashtable فارغًا.
بغض النظر عن HashMap أو Hashtable، إذا لاحظنا منشئه، فسنجد أنه يمكن أن يحتوي على معلمتين: السعة الأولية وقيمة التحميل افتراضيًا، السعة الأولية تساوي 16 وعامل التحميل يساوي 0.75. يرتبط هذا بعدد العناصر التي يمكن تخزينها في جدول التجزئة. عندما يتجاوز عدد العناصر السعة الأولية * عامل التحميل، سيتم تشغيل طريقة إعادة التجزئة لتوسيع جدول التجزئة. إذا أردنا إدراج الكثير من العناصر فيه، فسنحتاج إلى ضبط هاتين المعلمتين بشكل مناسب.
دعونا نلقي نظرة أولاً على مثال HashMap:
Map.put(new Integer(1), "a");
Map.put(new Integer(2), "b");
Map.put(new Integer(3), "c");
System.out.println(map);
System.out.println(map.entrySet());
System.out.println(map.keySet());
System.out.println(map.values());
}
Map.put(null, null);
Map.put(null, null);
Map.put(new Integer(4), null);
Map.put(new Integer(5), null);
System.out.println(map);
System.out.println(map.entrySet());
System.out.println(map.keySet());
System.out.println(map.values());
}
table.put(new Integer(1), "a");
table.put(new Integer(2), "b");
table.put(new Integer(3), "c");
System.out.println(table);
System.out.println(table.entrySet());
System.out.println(table.keySet());
System.out.println(table.values());
}
hashTableTest2 () باطلة ثابتة خاصة
{
Map<Integer,String> table = new Hashtable<Integer, String>();
table.put(null, null);
table.put(null, null);
table.put(new Integer(4), null);
table.put(new Integer(5), null);
System.out.println(table);
System.out.println(table.entrySet());
System.out.println(table.keySet());
System.out.println(table.values());
}
تشير خريطة الفرز بشكل أساسي إلى TreeMap، التي لها تعقيد زمني يبلغ O(log(n)) عند إضافة العناصر وحذفها والبحث عنها. إنها ليست آمنة للخيط.
خصائصه مشابهة جدًا لـ TreeSet، لذا لن أخوض في التفاصيل هنا.