2009-06-18 38 views
24

Tôi có một triệu hàng dữ liệu ở định dạng .txt. định dạng rất đơn giản. Đối với mỗi hàng:Cách tốt nhất để tạo một hashmap của arraylist

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

Bạn biết ý tôi là gì. Đối với mỗi người dùng, nó có thể xuất hiện nhiều lần, hoặc chỉ xuất hiện một lần (bạn không bao giờ biết). Tôi cần phải tìm hiểu tất cả các giá trị cho mỗi người dùng. Bởi vì người dùng có thể xuất hiện ngẫu nhiên, tôi đã sử dụng Hashmap để làm điều đó. Đó là: HashMap (key: String, value: ArrayList). Nhưng để thêm dữ liệu vào arrayList, tôi phải liên tục sử dụng HashMap get (key) để lấy arrayList, thêm giá trị vào nó, sau đó đặt nó trở lại HashMap. Tôi cảm thấy nó không phải là rất hiệu quả. Có ai biết cách tốt hơn để làm điều đó không?

Trả lời

61

Bạn không cần phải thêm lại ArrayList vào Bản đồ của mình. Nếu ArrayList đã tồn tại thì chỉ cần thêm giá trị của bạn vào nó.

An thực hiện cải tiến có thể trông giống như:

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

trong khi chế biến mỗi dòng:

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); 

Follow-up tháng 4 năm 2014 - tôi đã viết câu trả lời ban đầu trở lại trong năm 2009 khi kiến ​​thức của tôi Google Guava bị giới hạn. Theo tất cả những gì mà Google Guava thực hiện, tôi khuyên bạn nên sử dụng số Multimap thay vì tạo lại nó.

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")); 

Đầu ra:

[value4, value1] 
[value2] 
[value3] 
+0

Các câu trả lời khác đều đúng. Tôi chỉ không muốn sử dụng thư viện bên ngoài. –

+0

Đây là một cuộc sống tiết kiệm, cảm ơn. – wirbly

-1

sẽ nhanh hơn nếu bạn sử dụng LinkedList thay vì ArrayList, vì ArrayList sẽ cần phải thay đổi kích thước khi nó gần dung lượng.

bạn cũng sẽ muốn ước tính một cách thích hợp dung lượng của bộ sưu tập gói (HashMap hoặc Multimap) mà bạn đang tạo để tránh việc khôi phục lặp đi lặp lại.

+2

ArrayList gần như chắc chắn sẽ có hiệu suất trung bình tốt hơn, ngay cả khi thay đổi kích thước. LinkedList là một lựa chọn tốt đẹp khi bạn muốn tất cả các hoạt động của mình thực hiện cùng một khoảng thời gian, ví dụ: chúng có liên quan đến giao diện người dùng và bạn không muốn sự chậm trễ ngẫu nhiên khi người dùng thực hiện một hành động. –

4

Các giá trị ArrayList trong HashMap của bạn là tài liệu tham khảo. Bạn không cần phải "đặt nó trở lại HashMap". Bạn đang hoạt động trên đối tượng đã tồn tại dưới dạng giá trị trong HashMap.

1

tôi nghĩ điều bạn muốn là Multimap. Bạn có thể lấy nó từ bộ sưu tập commons's commons, hoặc bộ sưu tập google.

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

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

"bộ sưu tập tương tự như một bản đồ, nhưng mà có thể kết hợp nhiều giá trị với một chìa khóa duy nhất. Nếu bạn gọi đặt (K, V) hai lần, với cùng một khóa nhưng các giá trị khác nhau, multimap chứa ánh xạ từ khóa tới cả hai giá trị . "

-1

Như đã đề cập, MultiMap là lựa chọn tốt nhất của bạn.

Tùy thuộc vào yêu cầu kinh doanh hoặc ràng buộc của bạn trên tệp dữ liệu, bạn có thể cân nhắc thực hiện sắp xếp một lần, để làm cho nó được tối ưu hóa hơn để tải.

+1

Đây phải là một nhận xét –

0

Tôi không thể tìm thấy bất kỳ cách nào dễ dàng. MultiMap không phải luôn luôn là một tùy chọn có sẵn. Vì vậy, tôi đã viết một cái gì đó này.

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

Nếu bạn không muốn nhập thư viện.

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

Một ví dụ điển hình về giải pháp Java API cốt lõi. Cảm ơn bạn, – Loa

Các vấn đề liên quan