كيفية استخدام IndexOf في قائمة تحتوي على HashMap مع أزواج مفاتيح/قيمة متعددة

StackOverflow https://stackoverflow.com/questions/9009491

سؤال

انا املك List تحتوي HashMaps.كل HashMap في القائمة قد يكون لها عدة key/value أزواج.أريد أن indexOf في القائمة لمعرفة فهرس العنصر الذي تم تمريره في HashMap.ومع ذلك، فإن المشكلة هي أن هطريقة quals من HashMap ينظر إلى كل كله entrySet أثناء المقارنة.وهذا ليس ما أريد.

مثال:

    List<HashMap> benefit = new ArrayList<HashMap>();
    HashMap map1 = new HashMap();
    map1.put("number", "1");
    benefit.add(map1);
    HashMap map2 = new HashMap();
    map2.put("number", "2");
    map2.put("somethingelse", "blahblah"); //1
    benefit.add(map2);

    HashMap find = new HashMap();
    find.put("number", "2");
    int index = benefit.indexOf(find);
    if (index >= 0)
        System.out.println(benefit.get(index).get("number"));

الكود أعلاه لا يطبع أي شيء بسبب السطر with //1.

  • ما الذي يجب علي فعله حتى تتم طباعة الكود أعلاه بالفعل 2?
  • هل هناك طريقة لتنفيذ قابلة للمقارنة في القائمة حتى أتمكن من تحديد خاص بي؟
هل كانت مفيدة؟

المحلول

أعتقد أنك تبحث عنه retainAll(), ، حتى تتمكن من مقارنة العناصر التي تهمك فقط:

int index = myIndexOf(benefit, find);

...

static int myIndexOf(List<HashMap> benefit, Map find) {
    int i = 0;
    for (Map map : benefit) {
        Map tmp = new HashMap(map);
        tmp.keySet().retainAll(find.keySet());
        if (tmp.equals(find)) {
            return i;
        }
        i++;
    }
    return -1;
}

من الممكن، بالطبع، الإعلان عن فئة فرعية خاصة بك من القائمة والتي تتجاوز طريقة IndexOf بهذا السلوك.ومع ذلك، لا أعتقد أن هذه فكرة جيدة.من شأنه أن ينتهك عقد طريقة IndexOf:

تُرجع أدنى فهرس i بحيث (o==null ؟الحصول على (ط) == فارغة :س. يساوي (الحصول على (ط)))

قد يكون هذا مربكًا لشخص آخر يحافظ على الكود.قد تعتقد بعد ذلك أنه يمكنك استخدام فئة فرعية HashMap لإعادة تعريف يساوي، ولكن هذا من شأنه أن ينتهك خاصية التناظر في Object.equals().

نصائح أخرى

الطريقة التي تحاول بها تحقيق هدفك خاطئة.ال indexOf تعمل الطريقة تمامًا كما ينبغي في هذه الحالة.إنها تحاول العثور على تطابق تام، وليس تطابقًا جزئيًا.

ما تحاول القيام به، إذا فهمته بشكل صحيح، هو العثور على خريطة في قائمة الخرائط التي تحتوي على إدخال محدد.في هذه الحالة، يجب عليك إجراء هذا البحث يدويًا، من خلال تصفح جميع الخرائط، والاتصال containsKey (), ، ثم قم بمقارنة القيمة التي تتوقع العثور عليها مع القيمة المرتبطة بالمفتاح.

الطريقة الأخرى هي إنشاء فئة وكيل حول ملفك List, ، وأضف طريقة جديدة findMapWithEntry (String key, String value), ، والذي من شأنه أن يؤدي هذا البحث لك (نفس البحث الذي وصفته أعلاه).

لماذا لا تغير طريقة البحث؟

List<Map> matchingBenefits = new ArrayList<Map>();
for (Map m : benefit) {
    if (m.containsKey("number") && m.get("number").equals("2"))
        matchingBenefits.add(m);
}
for (Map m : matchingBenefits) {
    System.out.println(m.get("number"));
}

يمكنك دائمًا تجاوز طريقة IndexOf.النظر إلى مصدر ArrayList:

   public int indexOf(Object o) {
     if (o == null) {
       for (int i = 0; i < size; i++)
         if (elementData[i]==null)
          return i;
     else {
       for (int i = 0; i < size; i++)
         if (o.equals(elementData[i]))
           return i;
     }
     return -1;
   }

لذلك فهي ليست خوارزمية بحث معقدة للغاية على الإطلاق.قد تنظر إلى شيء مثل:

List benefit = new ArrayList(){
 public int indexOf(Object o){
      if (o == null) {
        for (int i = 0; i < size; i++)
         if (elementData[i]==null)
           return i;
      else {
        for (int i = 0; i < size; i++) //traverse the hashmaps
         Object key = ((HashMap)o).keySet().get(0); //assuming one pair
         Object val = ((HashMap)o).valueSet().get(0);
         if (
            ((HashMap)elementData[i]).containsKey(key) &&             
            ((HashMap)elementData[i]).get(key).equals(val))
              return i;
      }
      return -1;
 };

نصيحتي هي التفكير في بنية بيانات مختلفة، وربما كتابة هيكل خاص بك لها.

نظرًا لأنه لا يمكنك تغيير التصميم، فهل كتابة طريقة البحث الخاصة بك ستساعد؟

يجب أن يعمل الكود أدناه إذا فهمت ما تحاول القيام به ويعمل في O(n)

public static String find(List<HashMap<String,String>> listMap, String key, String value) {
    for(int i = 0; i < listMap.size(); i++)
        if(listMap.get(i).get(key).equals(value))
            return value;

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