2009-06-18 4 views
24

.txt 형식의 1 백만 행 데이터가 있습니다. 형식은 매우 간단합니다. 각 행에 대해 :arraylist의 해시 맵을 만드는 가장 좋은 방법

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

내가 무슨 뜻인지 알지. 각 사용자마다 여러 번 나타날 수도 있고 한 번만 나타날 수도 있습니다. 각 사용자에 대한 모든 값을 찾아야합니다. 사용자가 무작위로 나타날 수 있으므로 해시 맵을 사용했습니다. 즉 : HashMap (key : String, value : ArrayList)입니다. 그러나 arrayList에 데이터를 추가하려면 HashMap get (key)을 사용하여 arrayList를 가져 와서 값을 추가 한 다음 다시 HashMap에 넣어야합니다. 나는 그렇게 효율적이지 않다고 느낍니다. 더 좋은 방법은 누구나 아는가?

답변

61

다시 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년 4월를 - 내가 2009 년에 다시 원래의 답을 쓸 때의 내 지식 Google 구아바는 제한되었습니다. Google 구아바가하는 모든 측면을 고려하여 지금은 재발행하는 대신 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] 
+0

다른 답변은 모두 정확합니다. 나는 외부의 도서관을 사용하고 싶지 않다. –

+0

이것은 생명의 은인, 감사합니다. – wirbly

-1

ArrayList 대신 LinkedList를 사용하면 ArrayList의 용량이 가까워지면 크기를 조정해야하므로 더 빠릅니다.

재 포장을 반복하지 않으려는 래핑 모음 (HashMap 또는 Multimap)의 용량을 적절하게 예측할 수도 있습니다.

+2

ArrayList는 크기 조정시에도 평균 성능이 거의 확실합니다. LinkedList는 모든 작업이 거의 동일한 시간 (예 : UI에 관련되어 있고 사용자가 작업을 수행 할 때 임의의 지연을 원하지 않는 경우)을 원할 때 좋은 선택입니다. –

4

당신의 HashMap의 ArrayList에 값이 참조입니다에 대해 여러 값을 허용합니다. "다시 HashMap에 저장"할 필요가 없습니다. 이미 HashMap에 값으로 존재하는 객체에서 작업하고 있습니다.

1

내가 원하는 것은 Multimap이라고 생각합니다. 아파치의 커먼즈 콜렉션이나 구글 콜렉션에서 가져올 수 있습니다.

http://commons.apache.org/collections/ 두 번

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

하나의 키와 를 여러 값을 연결할 수

"지도와 유사 수집하지만, . 당신은 넣어 호출하면 (K, V)에서와 동일한 키이지만 값이 다르면 멀티 맵 에 키의 매핑과 값의 매핑이 모두 포함되어 있습니다. "

-1

, MultiMap는 당신의 최선의 선택입니다.

비즈니스 요구 사항이나 데이터 파일의 제약 사항에 따라로드 최적화를 위해 일회성 정렬을 고려하는 것이 좋습니다.

+1

이것은 코멘트 여야합니다 –

0

나는 쉬운 방법을 찾지 못했습니다. 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; 
    } 
} 
3

라이브러리를 가져 오지 않으려는 경우.

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;  
    }  
    }  
}  
+0

핵심 Java API 솔루션의 좋은 예입니다. 고맙습니다, – Loa