English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

تعليمية Java الأساسية

تحكم Java في العملية

مجموعات Java Array

Java Object-Oriented (I)

Java Object-Oriented (II)

Java Object-Oriented (III)

معالجة الاستثناءات في Java

قوائم Java List

Java Queue (الصف)

مجموعات Java Map

مجموعات Java Set

Java Input/Output (I/O)

Java Reader/Writer

مواضيع Java أخرى

Java ConcurrentHashMap

في هذا الدرس، سنستخدم الأمثلة لدراسة فئة Java ConcurrentHashMap وعملياتها.

فئة ConcurrentHashMap في إطار Java Collections Framework توفر خريطة التباين آمنة من حيث الاستخدام المتوازي. بمعنى آخر، يمكن للعديد من الخلايا الوصول إلى الخريطة في نفس الوقت دون تأثير على توازن عناصر الخريطة.

إنها تنحدر منواجهة ConcurrentMap.

إنشاء ConcurrentHashMap

لإنشاء خريطة البحث المتوازية، يجب علينا أولاً استيراد مكتبة java.util.concurrent.ConcurrentHashMap. بعد استيراد المكتبة، يمكننا إنشاء خريطة التباين في Java.

// ConcurrentHashMap بقدرة 8 وعامل تحميل 0.6
ConcurrentHashMap<Key, Value> numbers = new ConcurrentHashMap<>(8, 0.6f);

في الكود أعلاه، قمنا بإنشاء خريطة متوازية اسمها numbers.

في هذا السياق،

  • Key - الميزة الفريدة المستخدمة للربط بكل عنصر (قيمة) في الخريطة

  • Value - العنصر المرتبط بكائن الخريطة

لاحظ جملة new ConcurrentHashMap<>(8, 0.6). هنا، الأول هوcapacity، الثانية هيloadFactor.

  • capacity - سعة هذه الخريطة هي 8. هذا يعني، يمكنها تخزين 8 مدخل.

  • loadFactor- عامل تحميل هذه الخريطة هو 0.6. هذا يعني، بمجرد أن تكون قائمة جدول التوزيع مليئة بنسبة 60 في المئة، ستنتقل المدخلات إلى جدول توزيع جديد بحجم ضعف جدول التوزيع الأصلي.

قدرة افتراضية و عامل تحميل افتراضي

لا تحتاج إلى تعريف قدرتها وعامل تحميلها لإنشاء خريطة متوازية. على سبيل المثال،

// ConcurrentHashMap بقدرة افتراضية و عامل تحميل افتراضي
ConcurrentHashMap<Key, Value> numbers1 = new ConcurrentHashMap<>();

افتراضيًا،

  • سعة الخريطة ستكون 16

  • عامل التحميل سيكون 0.75

إنشاء ConcurrentHashMap من خريطة أخرى

هذا كيفية إنشاء hashmap متوازية تحتوي على جميع العناصر من خريطة أخرى.

import java.util.concurrent.ConcurrentHashMap;
import java.util.HashMap;
class Main {
    public static void main(String[] args) {
        // إنشاء hashmap للعدد المزدوج
        HashMap<String, Integer> evenNumbers = new HashMap<>();
        evenNumbers.put("Two", 2)
        evenNumbers.put("Four", 4)
        System.out.println("HashMap: " + evenNumbers);
        // من إنشاء hashmap متوازية من خريطة أخرى
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(evenNumbers);
        numbers.put("Three", 3);
        System.out.println("ConcurrentHashMap: " + numbers);
    }
}

نتائج الإخراج

HashMap: {Four=4, Two=2}
ConcurrentHashMap: {Four=4, Two=2, Three=3}

طريقة ConcurrentHashMap

يقدم فئة ConcurrentHashMap طرقًا تسمح لنا بتنفيذ مجموعة متنوعة من العمليات على المapping

إدراج العنصر في ConcurrentHashMap

  • put() - أضف المفتاح/القيمة المحدد إلى المapping

  • putAll() - أضف جميع المدخلات في المapping المحدد إلى هذا المapping

  • putIfAbsent() - إذا لم يكن المفتاح المحدد موجودًا في المapping، فأضف المفتاح/القيمة المحدد إلى المapping

على سبيل المثال،

import java.util.concurrent.ConcurrentHashMap;
class Main {
    public static void main(String[] args) {
        //إنشاء ConcurrentHashMap من الأعداد الزوجية
        ConcurrentHashMap<String, Integer> evenNumbers = new ConcurrentHashMap<>()
        // استخدام put()
        evenNumbers.put("Two", 2)
        evenNumbers.put("Four", 4)
        // استخدام putIfAbsent()
        evenNumbers.putIfAbsent("Six", 6)
        System.out.println("ConcurrentHashMap من الأعداد الزوجية: " + evenNumbers)
        //إنشاء ConcurrentHashMap من numbers
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
        numbers.put("One", 1);
        // استخدام putAll()
        numbers.putAll(evenNumbers)
        System.out.println("رقم ConcurrentHashMap هو: " + numbers)
    }
}

نتائج الإخراج

ConcurrentHashMap من الأعداد الزوجية: {Six=6, Four=4, Two=2}
رقم ConcurrentHashMap هو: {Six=6, One=1, Four=-4, Two=2}

زيارة عناصر ConcurrentHashMap

1.استخدام entrySet()،keySet() وvalues()

  • entrySet() - عودة مجموعة من جميع المفاتيح/القيم

  • keySet() - عودة مجموعة المفاتيح لكل مفتاح في المفتاح

  • values() - عودة مجموعة القيم لكل قيمة في المفتاح

على سبيل المثال،

import java.util.concurrent.ConcurrentHashMap;
class Main {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
        numbers.put("One", 1);
        numbers.put("Two", 2);
        numbers.put("Three", 3);
        System.out.println("ConcurrentHashMap: " + numbers);
        // استخدام entrySet()
        System.out.println("م映射 مفتاح/قيمة: " + numbers.entrySet())
        // استخدام keySet()
        System.out.println("مفاتيح: " + numbers.keySet())
        // استخدام values()
        System.out.println("القيم: " + numbers.values());
    }
}

نتائج الإخراج

ConcurrentHashMap: {One=1, Two=2, Three=3}
映射 مفتاح/قيمة: [One=1, Two=2, Three=3]
المفاتيح: [One, Two, Three]
القيم: [1, 2, 3]

2. استخدام get() وgetOrDefault()

  • get() - يعود القيمة المرتبطة بالمفتاح المحدد. إذا لم يتم العثور على المفتاح، يتم العودة إلى null.

  • getOrDefault() - يعود القيمة المرتبطة بالمفتاح المحدد. إذا لم يتم العثور على المفتاح، يتم العودة إلى القيمة المحددة كافتراض.

على سبيل المثال،

import java.util.concurrent.ConcurrentHashMap;
class Main {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
        numbers.put("One", 1);
        numbers.put("Two", 2);
        numbers.put("Three", 3);
        System.out.println("ConcurrentHashMap: " + numbers);
        // استخدام get()
        int value1 = numbers.get("Three");
        System.out.println("استخدام get(): " + value1);
        // استخدام getOrDefault()
        int value2 = numbers.getOrDefault("Five", 5);
        System.out.println("استخدام getOrDefault(): " + value2);
    }
}

نتائج الإخراج

ConcurrentHashMap: {One=1, Two=2, Three=3}
استخدام get(): 3
استخدام getOrDefault(): 5

حذف عناصر ConcurrentHashMap

  • remove(key) - يعود ويحذف العنصر المرتبط بالمفتاح المحدد من الخريطة.

  • remove(key, value) - يتم حذف العنصر من الخريطة فقط إذا كان المفتاح مرتبطًا بالقيمة المحددة ويعود قيمة صحيحة.

على سبيل المثال،

import java.util.concurrent.ConcurrentHashMap;
class Main {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
        numbers.put("One", 1);
        numbers.put("Two", 2);
        numbers.put("Three", 3);
        System.out.println("ConcurrentHashMap: " + numbers);
        // طريقة الحذف بمعامل واحد
        int value = numbers.remove("Two");
        System.out.println("القيمة المحذوفة: " + value);
        // طريقة الحذف بثلاثة أ参数
        boolean result = numbers.remove("Three", 3);
        System.out.println("هل تم حذف العنصر {Three=3}? " + result);
        System.out.println("ConcurrentHashMap بعد التحديث: " + numbers);
    }
}

نتائج الإخراج

ConcurrentHashMap: {One=1, Two=2, Three=3}
القيمة المحذوفة: 2
هل تم حذف العنصر {Three=3}? True
ConcurrentHashMap بعد التحديث: {One=1}

طرق العمليات الجماعية لـ ConcurrentHashMap

يقدم类 ConcurrentHashMap طرق جماعية يمكن تطبيقها بشكل آمن في العمليات المتوازية لـ map المختلفة.

1. طريقة forEach()

يتم تمرير طريقة forEach() عبر عناصرنا ويتم تنفيذ الدالة المحددة.

يحتوي على متغيرين

  • parallelismThreshold - يحدد عدد العناصر التي يتم تنفيذها بشكل متوازي في الخريطة.

  • transformer - سيتم تحويل البيانات قبل نقلها إلى الدالة المحددة.

على سبيل المثال،

import java.util.concurrent.ConcurrentHashMap;
class Main {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
        numbers.put("One", 1);
        numbers.put("Two", 2);
        numbers.put("Three", 3);
        System.out.println("ConcurrentHashMap: " + numbers);
        // forEach() لا يحتوي على الدالة المحددة
        numbers.forEach(4, (k, v) -> System.out.println("المفتاح: " + k + " القيمة: " + v));
        // يتم نقل الدالة المحددة إلى forEach()
        System.out.print("القيم هي ");
        numbers.forEach(4, (k, v) -> v, (v) -> System.out.print(v + ", "));
    }
}

نتائج الإخراج

ConcurrentHashMap: {واحد = 1, إثنين = 2, ثلاثة = 3}
المفتاح: واحد القيمة: 1
المفتاح: اثنين القيمة: 2
المفتاح: ثلاثة القيمة: 3
القيم هي 1, 2, 3,

في البرنامج أعلاه، استخدمنا معامل الحد الأدنى للتنفيذ المتوازي4هذا يعني، إذا كانت الخريطة تحتوي على 4 عناصر، فإن العملية ستتم بشكل متوازي.

تنوعات طريقة forEach()

  • forEachEntry() - تنفيذ الدالة المحددة لكل عنصر

  • forEachKey() - تنفيذ الدالة المحددة لكل مفتاح

  • forEachValue() - تنفيذ الدالة المحددة لكل قيمة

2. طريقة search()

يبحث طريقة search() في الخريطة بناءً على الدالة المحددة ويقوم بإرجاع العنصر المطابق.

في هذا السياق، يحدد الدالة المحددة ما سيتم البحث عنه.

إضافةً إلى ذلك، يحتوي على معامل اختياري called parallelThreshold. معامل الحد الأدنى للتنفيذ المتوازي هو عدد العناصر في الخريطة بعد تنفيذ العملية بشكل متوازي.

على سبيل المثال،

import java.util.concurrent.ConcurrentHashMap;
class Main {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
        numbers.put("One", 1);
        numbers.put("Two", 2);
        numbers.put("Three", 3);
        System.out.println("ConcurrentHashMap: " + numbers);
        // استخدام search()
        String key = numbers.search(4, (k, v) -> {return v == 3 ? k: null;});
        System.out.println("القيمة البحثية: " + key);
    }
}

نتائج الإخراج

ConcurrentHashMap: {One=1, Two=2, Three=3}
القيمة البحثية: ثلاثة

تنوعات طريقة search()

  • searchEntries() - الحالة البحثية تطبق على خريطة الأكواد/القيم

  • searchKeys() - الحالة البحثية تنطبق فقط على الأكواد

  • searchValues() - الحالة البحثية تنطبق فقط على القيم

3. طريقة reduce()

يحفظ طريقة reduce() كل مدخل في الخريطة. يمكن استخدام هذه الطريقة عندما نحتاج إلى جميع المدخلات لتنفيذ مهمة شائعة (مثل جمع جميع القيم في الخريطة)

يحتوي على متغيرين

  • parallelismThreshold - يحدد بعد عدد العناصر، يتم تنفيذ عمليات map بشكل متوازي

  • transformer - سيتم تحويل البيانات قبل تمريرها إلى الوظيفة المحددة

على سبيل المثال،

import java.util.concurrent.ConcurrentHashMap;
class Main {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
        numbers.put("One", 1);
        numbers.put("Two", 2);
        numbers.put("Three", 3);
        System.out.println("ConcurrentHashMap: " + numbers);
        // استخدام search()
        int sum = numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1 + v2);
        System.out.println("مجموع جميع القيم: " + sum);
    }
}

نتائج الإخراج

ConcurrentHashMap: {One=1, Two=2, Three=3}
مجموع جميع القيم: 6

في البرنامج أعلاه، لاحظ الجمل التالية

numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1+v2);

في هذا السياق،

  • 4 هو عتبة التنفيذ المتوازي

  • (k, v) -> v هو وظيفة تحويل. يحوّل خريطة المفاتيح/القيم فقط إلى القيم.

  • (v1, v2) -> v1+v2 هو وظيفة حساب الحجم. يجمع جميع القيم ويضيف جميع القيم معًا.

مشاريع طريقة reduce()

  • reduceEntries() - عودة نتيجة جمع جميع المدخلات باستخدام الوظيفة المحددة للمخفض

  • reduceKeys() - عودة نتيجة جمع جميع المفاتيح باستخدام الوظيفة المحددة للمخفض

  • reduceValues() - عودة نتيجة جمع جميع القيم باستخدام الوظيفة المحددة للمخفض

الفرق بين ConcurrentHashMap و HashMap

إليك الفرق بين ConcurrentHashMap وHashMapبعض الفروق بين

  • ConcurrentHashMap هوآمنة للتعامل مع النواةالمجموعات. بمعنى آخر، يمكن للعديد من النواة الوصول إليها وتعديلها في نفس الوقت.

  • يقدم ConcurrentHashMap طرقًا用于 العمليات الجماعية مثل forEach()، search() و reduce().

لماذا اختيار ConcurrentHashMap؟

  • فئة ConcurrentHashMap تسمح بإجراء عمليات التعديل المتوازية من قبل عدة نواة.

  • بافتراض الافتراض، يتم تقسيم خريطة ConcurrentHashMap إلىالفقرة 16لذا، يُسمح بتعديل خريطة من قبل 16 نواة في نفس الوقت. ولكن يمكن الوصول إليها من قبل أي عدد من النواة في وقت واحد.

  • إذا كان المفتاح المحدد موجودًا بالفعل، فإن طريقة putIfAbsent() لن تغطي المدخل في الخريطة.