Arraylist의 해시 맵을 만드는 가장 좋은 방법
-
06-07-2019 - |
문제
.txt 형식으로 백만 행의 데이터가 있습니다. 형식은 매우 간단합니다. 각 행에 대해 :
user1,value1 user2,value2 user3,value3 user1,value4 ...
당신은 내가 무슨 뜻인지 알고 있습니다. 각 사용자의 경우 여러 번 나타나거나 한 번만 나타날 수 있습니다 (알 수 없습니다). 각 사용자의 모든 값을 찾아야합니다. 사용자가 무작위로 나타날 수 있으므로 해시 맵을 사용하여 수행했습니다. 즉, 해시 맵 (키 : 문자열, 값 : ArrayList). 그러나 Arraylist에 데이터를 추가하려면 Arraylist를 얻으려면 Hashmap get (key)을 지속적으로 사용하여 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 월 - Google Guava에 대한 지식이 제한되어 2009 년에 원래 답변을 썼습니다. Google Guava가하는 모든 일에 비추어 이제는 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]
다른 팁
Google 컬렉션에서 멀티 맵을 사용하십시오. 동일한 키에 대해 여러 값을 허용합니다
https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/multimap.html
해시 맵의 배열리스트 값은 참조입니다. "해시 맵에 다시 넣을 필요가 없습니다". 해시 맵의 값으로 이미 존재하는 객체에서 작동하고 있습니다.
라이브러리를 가져오고 싶지 않은 경우.
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
Collection<String> values = map.computeIfAbsent(user, k -> new ArrayList<>());
values.add(value);
나는 당신이 원하는 것이 멀티 맵이라고 생각합니다. Apache의 Commons Collection 또는 Google 수집에서 얻을 수 있습니다.
http://commons.apache.org/collections/
http://code.google.com/p/google-collection/
"맵과 비슷하지만 여러 값을 단일 키와 연관시킬 수 있습니다. 풋 (k, v)을 두 번 호출하면 동일한 키이지만 다른 값으로 두 번 호출하면 멀티 맵에는 키에서 두 값으로 매핑이 포함되어 있습니다."
쉬운 방법을 찾을 수 없었습니다. 멀티 맵이 항상 사용할 수있는 옵션은 아닙니다. 그래서 나는 이것을 썼습니다.
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 대신 LinkedList를 사용하면 더 빠릅니다.
또한 반복적 인 재료를 피하기 위해 만들고있는 포장 컬렉션 (해시 맵 또는 멀티 맵)의 용량을 적절하게 추정하고자합니다.
이미 언급했듯이 MultiMap
최선의 선택입니다.
데이터 파일의 비즈니스 요구 사항 또는 제약 조건에 따라 일회성 정렬을 수행하여로드에보다 최적화하도록하는 것을 고려할 수 있습니다.