سؤال

لدي مليون صف من البيانات بتنسيق .txt.التنسيق بسيط جدًا.لكل صف:

user1,value1
user2,value2
user3,value3
user1,value4
...

أنت تعرف ما أعنيه.لكل مستخدم، يمكن أن يظهر عدة مرات، أو يظهر مرة واحدة فقط (لا تعرف أبدًا).أحتاج إلى معرفة جميع القيم لكل مستخدم.نظرًا لأن المستخدم قد يظهر بشكل عشوائي، فقد استخدمت Hashmap للقيام بذلك.إنه:خريطة التجزئة (المفتاح:قيمة السلسلة:قائمة المصفوفات).ولكن لإضافة بيانات إلى arrayList، لا بد لي من استخدام HashMap get(key) باستمرار للحصول على arrayList، وإضافة قيمة إليها، ثم إعادتها إلى HashMap.أشعر أنها ليست فعالة للغاية.هل يعرف أحد طريقة أفضل للقيام بذلك؟

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

المحلول

وأنت لا تحتاج إلى إعادة إضافته ArrayList إلى خريطة بك. إذا كان ArrayList موجود بالفعل بعد ذلك فقط إضافة قيمة لذلك.

وتنفيذا تحسين قد تبدو:

Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();

وأثناء معالجة كل سطر:

String user = user field from line
String value = value field from line

Collection<String> values = map.get(user);
if (values==null) {
    values = new ArrayList<String>();
    map.put(user, values)
}
values.add(value);

على متابعة أبريل 2014 - يمكنك كتبت الجواب الأصلية مرة أخرى في عام 2009 عندما كانت معرفتي جوجل الجوافة محدودة. في ضوء كل ذلك جوجل الجوافة يفعل، وأنا الآن نوصي باستخدام Multimap لها بدلا من إعادة اختراع ذلك.

Multimap<String, String> values = HashMultimap.create();
values.put("user1", "value1");
values.put("user2", "value2");
values.put("user3", "value3");
values.put("user1", "value4");

System.out.println(values.get("user1"));
System.out.println(values.get("user2"));
System.out.println(values.get("user3"));

والمخرجات:

[value4, value1]
[value2]
[value3]

نصائح أخرى

واستخدام Multimap من مجموعات جوجل. انها تسمح قيم متعددة لنفس المفتاح

الشبكي: / /google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Multimap.html

والقيم ArrayList في HashMap الخاصة بك المراجع. أنت لست بحاجة إلى أن "وضعه مرة أخرى إلى HashMap". كنت تعمل على كائن موجود بالفعل كقيمة في HashMap.

إذا كنت لا ترغب في استيراد المكتبة.

package util;    

import java.util.ArrayList;    
import java.util.HashMap;    
import java.util.List;    

/**    
 * A simple implementation of a MultiMap. This implementation allows duplicate elements in the the    
 * values. (I know classes like this are out there but the ones available to me didn't work).    
 */    
public class MultiMap<K, V> extends HashMap<K, List<V>> {    

  /**    
   * Looks for a list that is mapped to the given key. If there is not one then a new one is created    
   * mapped and has the value added to it.    
   *     
   * @param key    
   * @param value    
   * @return true if the list has already been created, false if a new list is created.    
   */    
  public boolean putOne(K key, V value) {    
    if (this.containsKey(key)) {    
      this.get(key).add(value);    
      return true;    
    } else {    
      List<V> values = new ArrayList<>();    
      values.add(value);    
      this.put(key, values);    
      return false;    
    }    
  }    
}    

ومنذ Java 8 يمكنك استخدام map.computeIfAbsent

<وأ href = "https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#computeIfAbsent-K-java.util.function.Function-" يختلط = " noreferrer نوفولو "> https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#computeIfAbsent-K-java.util.function.Function-

Collection<String> values = map.computeIfAbsent(user, k -> new ArrayList<>());
values.add(value);

أعتقد أن ما تريده هو Multimap.يمكنك الحصول عليه من مجموعة Apache Commons أو مجموعات Google.

http://commons.Apache.org/collections/

http://code.google.com/p/google-collections/

"مجموعة مماثلة لخريطة ، ولكن قد تربط قيم متعددة بمفتاح واحد.إذا قمت بالاتصال بـ PUT (k ، v) مرتين ، مع نفس المفتاح ولكن القيم المختلفة ، فإن multimap تحتوي على تعيينات من المفتاح إلى كلتا القيمتين. "

وأنا لا يمكن أن تجد أي وسيلة سهلة. MultiMap ليس دائما خيارا متاحا. لذلك كتبت هذا شيء.

public class Context<K, V> extends HashMap<K, V> {

    public V addMulti(K paramK, V paramV) {
        V value = get(paramK);
        if (value == null) {
            List<V> list = new ArrayList<V>();
            list.add(paramV);
            put(paramK, paramV);
        } else if (value instanceof List<?>) {
            ((List<V>)value).add(paramV);
        } else {
            List<V> list = new ArrayList<V>();
            list.add(value);
            list.add(paramV);
            put(paramK, (V) list);
        }
        return paramV;
    }
}

وأنه سيكون أسرع إذا كنت تستخدم قائمة متصلة بدلا من ArrayList، كما ArrayList سوف تحتاج إلى تغيير حجم عندما تقترب القدرات.

وسوف تحتاج أيضا إلى تقدير ملائم قدرة جمع التفاف (HashMap او Multimap) تقوم بإنشاء لتجنب باسترجاع المتكررة.

وكما سبق ذكره، MultiMap هو الخيار الأفضل.

واعتمادا على متطلبات عملك أو قيود على ملف البيانات، قد ترغب في النظر في القيام لمرة واحدة والفرز منه، لجعلها أكثر الأمثل للتحميل.

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