2012-03-18 24 views
6

Sử dụng các bộ sưu tập mới từ Google ổi của Google, http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplainedLàm cách nào để lặp qua Multimap theo thứ tự chèn?

Làm cách nào để lặp qua Bản đồ đa cho mỗi khóa theo thứ tự chèn?

Ví dụ

multimap = new HashMultiMap<String,String>(); 
multimap.put("1", "value1"); 
multimap.put("1", "value2"); 
multimap.put("1", "value3"); 

multimap.put("2", "value11"); 
multimap.put("2", "value22"); 
multimap.put("2", "value33"); 

multimap.put("3", "value111"); 
multimap.put("3", "value222"); 
multimap.put("3", "value333"); 

Trên mỗi vòng lặp Tôi cần

"value1", "value11", "value111"; 

sau đó vòng lặp tiếp theo

"value2", "value22", "value222"; 

và vân vân:

"value3", "value33", "value333"; 
+4

Bộ sưu tập 'băm *' không giữ nguyên thứ tự chèn. – SLaks

+0

trông giống như tôi cần phải sử dụng Bảng không phải là một MultiMap – KJW

Trả lời

11

Tôi không chắc chắn nhu cầu của bạn là gì (hoặc trường hợp sử dụng cụ thể), nhưng tôi sẽ cố gắng đoán. Các câu trả lời khác gợi ý sử dụng liên kết * Multimap hoặc không thể thay đổi, nhưng để có được kết quả mong muốn (hiển thị trong câu hỏi) với Multimap, bạn sẽ phải tạo một số Bản đồ ưa thích (tôi sẽ thảo luận sau) hoặc ví dụ: và giá trị thứ ba cho mỗi khóa (chúng sẽ được đặt theo thứ tự chèn, nếu bạn sử dụng một trong số các triển khai Multimap được đề xuất). Tốt nhất nó sẽ là một trong những ListMultimaps như bạn có thể duyệt qua multimap.keySet() để có được danh sách với giá trị có sẵn của chỉ số:

final ListMultimap<String,String> multimap = LinkedListMultimap.create(); 
// put values from question here 

final List<Object> firstValues = Lists.newArrayList(); 
for (final String key: multimap.keySet()) { 
    firstValues.add(multimap.get(key).get(0)); 
}  
System.out.println(firstValues); 
// prints [value1, value11, value111] 
// similar for multimap.get(key).get(1) and so on 

nhưng nhược điểm là bạn sẽ phải tạo ra ba Lists cho bạn ví dụ những gì làm cho giải pháp này khá không linh hoạt.Vì vậy, có lẽ nó sẽ được tốt hơn để đặt {đầu tiên, thứ hai, thứ ba} Giá trị thu vào Map>, những gì mang lại cho tôi vào vấn đề:


Có lẽ bạn nên sử dụng Table để thay thế?

Bảng được thiết kế như Một bộ sưu tập mà liên kết một cặp có thứ tự các phím, được gọi là một chìa khóa hàng và một phím cột, với một giá trị duy nhất và, có chuyện gì quan trọng hơn ở đây, có hàng và chế độ xem cột. Tôi sẽ sử dụng ArrayTable đây:

final ArrayTable<String, Integer, Object> table = ArrayTable.create(
    ImmutableList.of("1", "2", "3"), ImmutableList.of(0, 1, 2)); 

table.put("1", 0, "value1"); 
table.put("1", 1, "value2"); 
table.put("1", 2, "value3"); 

table.put("2", 0, "value11"); 
table.put("2", 1, "value22"); 
table.put("2", 2, "value33"); 

table.put("3", 0, "value111"); 
table.put("3", 1, "value222"); 
table.put("3", 2, "value333"); 

for (final Integer columnKey : table.columnKeyList()) { 
    System.out.println(table.column(columnKey).values()); 
} 
// prints: 
// [value1, value11, value111] 
// [value2, value22, value222] 
// [value3, value33, value333] 

Tôi cố tình sử dụng String cho phím hàng là [1, 2, 3, ...] Số nguyên trong thực tế (như bạn đã làm trong câu hỏi) và số nguyên cho các phím cột bắt đầu bằng 0 ([0, 1, 2, ...]) để hiển thị sự giống nhau với ví dụ trước bằng cách sử dụng bộ sưu tập của Danh sách get(int) trên các giá trị nhiều giá trị '.

Hy vọng điều này sẽ hữu ích, chủ yếu trong việc xác định những gì bạn muốn;)

P.S. Tôi sử dụng ArrayTable tại đây, bởi vì nó có cách tạo ra các giá trị hàng/khóa cố định (vũ trụ) hơn ImmutableTable, nhưng nếu không yêu cầu, bạn nên sử dụng nó thay vì một thay đổi - ImmutableTable (và bất kỳ triển khai Bảng nào khác) Không có phương pháp columnKeyList(), nhưng chỉ có columnKeySet() thực hiện tương tự, nhưng chậm hơn đối với ArrayTable. Và tất nhiên ImmutableTable.Builder hoặc ImmutableTable.copyOf(Table) nên được sử dụng.

+1

Tôi đã kết thúc bằng cách sử dụng bảng và lặp lại trên mỗi hàng, để có được một bản đồ đại diện cho toàn bộ hàng. – KJW

2

Đối với vòng lặp trên nhiều phím:

for (Object key : multimap.keys()) { ... } 

Bạn cũng có thể vòng qua các mục:

for (Map.Entry entry : multimap.entries()) { ... } 
+0

đây là nơi tôi bối rối, tôi thấy điều này trong một câu hỏi trước đó nhưng tôi không chắc chắn cách thức hoạt động này? Liệu nó có trả về tất cả các giá trị cho một khóa cụ thể hoặc trả về mỗi giá trị được liên kết với các khóa không? là có một ví dụ về điều này trong hành động? – KJW

4

Bạn có thể sử dụng một trong hai LinkedListMultimap hoặc LinkedHashMultimap.

Cả hai có hành vi rất giống nhau; một khác biệt chính là LinkedListMultimap cho phép nhiều bản sao của cùng một cặp khóa-giá trị được chèn vào, trong khi LinkedHashMultimap chỉ cho phép một.

Xem Javadoc được liên kết ở trên để biết thêm thông tin.

+0

Tôi không chắc chắn về điểm đầu tiên. Tôi đã thử với một ví dụ đang chạy và thứ tự lặp lại bằng cách sử dụng hai multimaps là giống nhau bằng cách sử dụng các khóa, giá trị, mục và asMap. – dawww

+1

@dawww: Rất tiếc, bạn đã đúng. Tôi phải hiểu sai tài liệu. Tôi sẽ loại bỏ dấu đầu dòng đó, cảm ơn. :-) – ruakh

3

Tôi không hoàn toàn rõ ràng những gì để lặp bạn có nghĩa là, OP ...

  • Set<K> keySet() chỉ trả về các phím.
  • Map<K, Collection<V>> asMap() trả về các phím và mục nhập liên quan của chúng, vì vậy bạn có thể làm for (Map.Entry<K, Collection<V>> entry : asMap().entrySet()) để lặp qua các khóa và các bộ sưu tập được liên kết của chúng.
  • Collection<Map.Entry<K, V>> entries() cho phép bạn lặp lại các mục nhập nhưng không nhất thiết phải nhóm chúng theo khóa.

Nếu bạn muốn mọi thứ theo thứ tự chèn, sử dụng một trong những chèn theo lệnh Multimap triển khai - LinkedHashMultimap, có thể LinkedListMultimap, ImmutableMultimap.

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