Java: بنية البيانات لتخزين المؤقت نتيجة حساب؟
-
20-09-2019 - |
سؤال
لدي حساب باهظ الثمن ، والنتيجة التي أرغب في ذاكرة التخزين المؤقت. هل هناك طريقة لإنشاء خريطة مع مفتاحين؟ أفكر في شيء مثل Map<(Thing1, Thing2), Integer>
.
ثم يمكنني التحقق:
if (! cache.contains(thing1, thing2)) {
return computeResult();
}
else {
return cache.getValue(thing1, thing2);
}
كود مزيف. لكن شيء على طول تلك الخطوط.
المحلول
تحتاج إلى إنشاء فصل يحمل الشيء 1 و thing2 ، على سبيل المثال:
class Things {
public final Thing1 thing1;
public final Thing2 thing2;
public Things(Thing1 thing1, Thing2 thing2) {
this.thing1 = thing1;
this.thing2 = thing2;
}
@Override
public boolean equals(Object obj) { ... }
@Override
public int hashCode() { ... };
}
ثم لاستخدامه:
Things key = new Things(thing1, thing2);
if (!cache.contains(key) {
Integer result = computeResult();
cache.put(key, result);
return result;
} else {
return cache.getValue(key);
}
لاحظ أنه يتعين عليك تنفيذ متساوٍ ورمز التجزئة لجعل هذا الرمز يعمل بشكل صحيح. إذا كنت بحاجة إلى أن يكون هذا الرمز آمنًا لخيط الخيط ، فاحرص على إلقاء نظرة على ConcurrentHashMap.
نصائح أخرى
يبدو أنك تريد المذكرات. أحدث رأس صندوق جافا الوظيفية لديه نوع منتج مذكرات P1
هذا النماذج حساب الذي تم تخزينه مؤقتًا.
سوف تستخدمه مثل هذا:
P1<Thing> myThing = new P1<Thing>() {
public Thing _1() {
return expensiveComputation();
}
}.memo();
استدعاء _1 () أول مرة ستقوم تشغيل الحساب باهظ الثمن وتخزينه في المذكرة. بعد ذلك ، يتم إرجاع المذكرة بدلاً من ذلك.
بالنسبة إلى "مفتاحين" ، تريد نوع زوج بسيط. Java الوظيفية لديها هذا أيضا في شكل الفصل P2<A, B>
. لمذكرات مثل هذه القيمة ، ببساطة استخدم P1<P2<A, B>>
.
يمكنك أيضا استخدام Promise<A>
الفصل بدلا من المذكرة. لقد كان هذا في المكتبة لفترة من الوقت ، لذلك ستحتاج فقط إلى أحدث ثنائي. يمكنك استخدام ذلك على النحو التالي:
Promise<Thing> myThing =
parModule(sequentialStrategy).promise(new P1<Thing>() {
public Thing _1() {
return expensiveComputation();
}
});
للحصول على النتيجة ، ببساطة اتصل myThing.claim()
. Promise<A>
يوفر أيضًا طرقًا لرسم الخرائط على النتيجة حتى لو لم تكن النتيجة جاهزة بعد.
تحتاج إلى import static fj.control.parallel.ParModule.parModule
و fj.control.parallel.Strategy.sequentialStrategy
. إذا كنت تريد أن يتم تشغيل الحساب في موضوعه الخاص ، استبدل sequentialStrategy
مع إحدى الاستراتيجيات الأخرى التي قدمتها Strategy
صف دراسي.
إذا كنت تستخدم مجموعات جوجل, ، إنه MapMaker
الفصل لديه makeComputingMap
الطريقة التي تفعل بالضبط ما وصفته. كمكافأة مجانية ، إنها أيضًا آمنة من الخيوط (تنفذ ConcurrentMap
).
أما بالنسبة للشيء المتوحشين ، فسيتعين عليك إنشاء فصل يحتوي على مفتاحين ، وتنفيذ تنفيذ مناسب لـ equals
, hashCode
, و (إن أمكن) compareTo
هذا يفعل المقارنة الرئيسية بالطريقة التي تريدها.