سؤال

انا املك java.util.HashMap هدف m (قيمة العودة من مكالمة إلى رمز Java) وأرغب في الحصول على خريطة جديدة مع زوج مفتاحي إضافي.

إذا m كانت خريطة عباءة، يمكنني استخدام:

(assoc m "key" "value")

ولكن تحاول ذلك على HashMap يعطي

java.lang.classcastexception: java.util.hashmap لا يمكن أن يلقي إلى clojure.lang.associative

لا حظ seq إما:

(assoc (seq m) "key" "value")

java.lang.classcastexception: clojure.lang.iteratorseq لا يمكن أن يلقي إلى clojure.lang.associative

الطريقة الوحيدة التي تمكنت من القيام بذلك كانت هي استخدام HashMapالخاصة put, ، ولكن هذا يعود void لذلك لا بد لي من العودة صراحة m:

(do (. m put "key" "value") m)

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

كيفية العمل مع HashMap في طريقة أكثر عباءة العش؟

هل كانت مفيدة؟

المحلول

Clojure يجعل مجموعات Java SEQ قادرة، حتى تتمكن من استخدام وظائف تسلسل عباءة مباشرة على java.util.hashmap..

ولكن مساعد تتوقع أ clojure.lang.associative. لذلك عليك أولا تحويل java.util.hashmap. إلى ذلك:

(assoc (zipmap (.keySet m) (.values m)) "key" "value")

تحرير: الحل أبسط:

(assoc (into {} m) "key" "value")

نصائح أخرى

إذا كنت تتلاشى مع رمز Java، فقد تضطر إلى عض الرصاصة وأفعلها بطريقة Java، باستخدام .put. وبعد هذه ليست بالضرورة خطيئة بشرية؛ يعطيك كلوي أشياء مثل do و . على وجه التحديد حتى تتمكن من العمل مع رمز Java بسهولة.

assoc يعمل فقط على هياكل بيانات Clojure لأن الكثير من العمل قد ذهبت إلى جعلها رخيصة جدا لإنشاء نسخ جديدة (غير قابلة للتغيير) منها مع تعديلات طفيفة. لا تهدف Gava Hashmaps إلى العمل بنفس الطريقة. يجب عليك الاستمرار في استنساخهم في كل مرة تقوم فيها بتغيير، والتي قد تكون مكلفة.

إذا كنت ترغب حقا في الخروج من أراضي طفرة Java (على سبيل المثال، فربما تبقي هذه الحشرات حولها لفترة طويلة ولا تريد أن تدعو Java في كل مكان، أو تحتاج إلى تسلسلها عبر print و read, ، أو أنك تريد العمل معهم بطريقة آمنة في الخيط باستخدام Clojure STM) يمكنك التحويل بين Java Hashmaps وخرائط Genh-Hash Clojure بسهولة كافية، لأن هياكل بيانات Clojure تنفذ واجهات Java الصحيحة حتى يتمكنوا من التحدث مع بعضهم البعض.

user> (java.util.HashMap. {:foo :bar})
#<HashMap {:foo=:bar}>

user> (into {} (java.util.HashMap. {:foo :bar}))
{:foo :bar}

إذا كنت تريد do- مثل الشيء الذي يعيد الكائن الذي تعمل عليه بمجرد الانتهاء من العمل عليه، يمكنك استخدامه doto. وبعد في الواقع، يستخدم Java Hashmap كمثال في الوثائق الرسمية لهذه الوظيفة، وهو مؤشر آخر على أنه ليس نهاية العالم إذا كنت تستخدم كائنات Java (بحكمة).

clojure.core/doto
([x & forms])
Macro
  Evaluates x then calls all of the methods and functions with the
  value of x supplied at the front of the given arguments.  The forms
  are evaluated in order.  Returns x.

  (doto (new java.util.HashMap) (.put "a" 1) (.put "b" 2))

بعض الاستراتيجيات الممكنة:

  1. الحد من طفيدتك والآثار الجانبية لوظيفة واحدة إذا استطعت. إذا كانت وظيفتك تقوم دائما بإرجاع نفس القيمة التي تعطى نفس المدخلات، فيمكنها أن تفعل ما تريد داخليا. في بعض الأحيان تكون صفيف أو خريطة هي الطريقة الأكثر كفاءة أو أسهل لتنفيذ الخوارزمية. ستظل الاستمتاع بفوائد البرمجة الوظيفية طالما أنك لا "تسرب" آثار جانبية لبقية العالم.

  2. إذا كانت الكائنات الخاصة بك ستكون موجودة لفترة من الوقت أو يحتاجون إلى اللعب بشكل جيد مع رمز عباءة أخرى، فحاول الحصول عليها في هياكل بيانات العبيدة في أقرب وقت ممكن، وإلقاءها مرة أخرى إلى Gava Hashmaps في الثانية الأخيرة (عند التغذية لهم العودة إلى جافا).

لا بأس بذلك تماما لاستخدام خريطة تجزئة Java بالطريقة التقليدية.
(do (. m put "key" "value") m)
This is not idiomatic Clojure code, plus I'm modifying m instead of creating a new map.

أنت تقوم بتعديل بنية البيانات التي يهدف حقا إلى تعديلها. خريطة تجزئة جافا تفتقر إلى المشاركة الهيكلية التي تسمح بنسخ خريطة العباءات بكفاءة. الطريقة الاصطلاحية عموما للقيام بذلك هي استخدام وظائف Java-Interop للعمل مع هياكل Java في طريقة Java النموذجية، أو لتحويلها بشكل نظيف إلى هياكل عباءة والعمل معها في طريقة العباءة الوظيفية. ما لم يكن بالطبع يجعل الحياة أسهل ونتائج في أفضل رمز؛ ثم جميع الرهانات خارج.

هذا هو بعض الكود الذي كتبته باستخدام HashMaps عندما كنت أحاول مقارنة خصائص الذاكرة لنسخة عباءة VS Java (ولكن المستخدمة من العباء)

(استيراد "(java.util hashtable)) (ترددات defn2 [coll] (دع [mydictable (hashtable جديد)] (تقليل (fn [counts x] (دع [y (. tollowcass x)] (إذا (. ) (. dutict meDict y (+ (. get meimdict y) 1)) (. dutict meDict y 1))

هذا هو أخذ بعض التحصيل والعودة إلى عدد المرات التي يتم فيها إعادة استخدام كل مرة كل شيء مختلف (يقول كلمة في سلسلة).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top