Làm cách nào để chuyển đổi Bản đồ thành Danh sách trong Java?


671

Cách tốt nhất để chuyển đổi a Map<key,value>thành a là List<value>gì? Chỉ cần lặp lại tất cả các giá trị và chèn chúng vào danh sách hoặc tôi đang xem xét một cái gì đó?


1
Tôi nghĩ đó không phải là một mô hình tốt nếu người ta phải chuyển đổi bản đồ thành danh sách. Người ta phải viết mã theo cách mà tình huống này không xảy ra.
Lỗi xảy ra

Câu trả lời:


1296
List<Value> list = new ArrayList<Value>(map.values());

giả định:

Map<Key,Value> map;

7
Cảm ơn! Tôi đã giả định các diễn viên từ Collectionđể Listcó thể làm việc.
asg

1
Tôi nghi ngờ lý do nó không hoạt động là vì bộ sưu tập được trả về bởi các giá trị () phụ thuộc vào Bản đồ cơ bản; bằng cách thực hiện cuộc gọi xây dựng bản sao thay vào đó, bạn phân bổ bộ nhớ và sao chép các giá trị vào bộ lưu trữ đó, do đó phá vỡ kết nối ...
Sheldon R.

4
Nếu chúng tôi có LinkedHashMap - đơn hàng sẽ giữ nguyên?

1
@ user2022068 có, đơn hàng nên được giữ nguyên với LinkedHashMap.
SusanW

1
@SheldonR. có - các bộ sưu tập được trả về bởi keySet()values()thường là các đối tượng shim cung cấp giao diện Set hoặc Collection cho cấu trúc bên dưới ( keySet()trả về Set để nhấn mạnh không có bản sao). Đối với values(), đối tượng trả về có thể là một List, nhưng thường sẽ không. Tạo một Danh sách thực, như bạn nói, phá vỡ liên kết có nghĩa là bạn không còn phụ thuộc vào Bản đồ gốc. Tuy nhiên, đôi khi, bạn chỉ cần một Danh sách vì một số API yêu cầu một - củng cố quy tắc rằng một API tốt chỉ nên yêu cầu các giao diện trừu tượng nhất mà nó có thể thoát khỏi ...
SusanW

137

Vấn đề ở đây là Mapcó hai giá trị (khóa và giá trị), trong khi Listchỉ có một giá trị (một phần tử).

Do đó, điều tốt nhất có thể được thực hiện là lấy một Listtrong các khóa hoặc các giá trị. (Trừ khi chúng tôi tạo một trình bao bọc để giữ cặp khóa / giá trị).

Nói rằng chúng tôi có một Map:

Map<String, String> m = new HashMap<String, String>();
m.put("Hello", "World");
m.put("Apple", "3.14");
m.put("Another", "Element");

Các khóa như một Listcó thể có được bằng cách tạo một cái mới ArrayListtừ một phương thức được Settrả về Map.keySet:

List<String> list = new ArrayList<String>(m.keySet());

Trong khi các giá trị dưới dạng Listcó thể thu được, tạo một giá trị mới ArrayListtừ phương thức Collectiontrả về Map.values:

List<String> list = new ArrayList<String>(m.values());

Kết quả của việc nhận được các Listphím:

táo
Khác
xin chào

Kết quả của việc nhận các Listgiá trị:

3.14
Thành phần
Thế giới

3
Cần lưu ý rằng thứ tự của các giá trị được trả về bởi các phương thức đó không được xác định và đối với HashMapcác Maptriển khai không được sắp xếp tương tự, nó sẽ có hiệu quả ngẫu nhiên.
Joachim Sauer

1
Có, bạn sẽ phải biết đó là LinkedHashMap hoặc một cái gì đó thuộc loại đó. Vấn đề với câu hỏi ban đầu là câu hỏi bị sai lệch, đó là nó cần chỉnh sửa. Câu hỏi không phải là chuyển đổi Bản đồ thành Danh sách, mà là làm thế nào để lấy các giá trị của bản đồ dưới dạng Danh sách. Các giá trị phương thức cung cấp cho bạn một Bộ sưu tập, nhưng không phải là một danh sách và do đó cần một mẹo nhỏ gọn gàng.
demongolem

Tôi nghĩ rằng bạn có thể thêm vào câu trả lời của mình những gì @ M0les nói: Rằng bạn sẽ cần phải "đi qua" SortedMap bằng cách nào đó. Bắt đầu với việc triển khai Sắp xếp Bản đồ cụ thể (Chẳng hạn như Bản đồ cây) hoặc chèn Bản đồ đầu vào của bạn vào Bản đồ được sắp xếp trước khi chuyển đổi thành Danh sách
Ignacio Rubio

41

Sử dụng API luồng Java 8.

List<Value> values = map.values().stream().collect(Collectors.toList());

8
Tôi thích câu trả lời được chấp nhận, dựa trên nhà xây dựng. Các luồng nên để đơn giản hóa mã.
Aaron

1
@Aaron Có, với nhiệm vụ lấy Danh sách các giá trị từ Map, hàm tạo dường như đơn giản hơn. Tuy nhiên, nếu bạn đang sử dụng Luồng một cách rộng rãi trong một cơ sở mã, tốt hơn hết là hãy kiên định.
Matej Kormuth

1
Khi tôi sử dụng điều này sẽ gặp lỗi nếu tôi đang tìm nạp một lượng lớn dữ liệu ..thread đang lặp trên java.util.stream.ReduceOps $ 3.makeSink (Nguồn không xác định). Nếu các luồng lặp lại vô hạn, mức tiêu thụ CPU sẽ bắt đầu tăng vọt. Dấu vết ngăn xếp chủ đề vòng lặp được đưa ra dưới đây, kiểm tra nó
Ganesh Giri

24

map.entrySet()cung cấp cho bạn một bộ sưu tập các Map.Entryđối tượng chứa cả khóa và giá trị. sau đó bạn có thể chuyển đổi nó thành bất kỳ đối tượng bộ sưu tập nào bạn thích, chẳng hạn như new ArrayList(map.entrySet());


23

một danh sách những gì?

Giả sử maplà ví dụ của bạn vềMap

  • map.values()sẽ trả về một Collectionchứa tất cả các giá trị của bản đồ.
  • map.keySet()sẽ trả về một Setchứa tất cả các khóa của bản đồ.

14

Tôi đoán bạn muốn chuyển đổi các giá trị có trong Mapa list? Dễ nhất là gọi values()phương thức của Mapgiao diện. Điều này sẽ trả về các Collectionđối tượng giá trị có trong Map.

Lưu ý rằng điều này Collectionđược hỗ trợ bởi Mapđối tượng và mọi thay đổi Mapđối tượng sẽ phản ánh ở đây. Vì vậy, nếu bạn muốn một bản sao riêng biệt không bị ràng buộc với Mapđối tượng của mình , chỉ cần tạo một Listđối tượng mới giống như ArrayListtruyền giá trị Collectionnhư bên dưới.

ArrayList<String> list = new ArrayList<String>(map.values());

6

Bạn có thể làm như thế này

List<Value> list = new ArrayList<Value>(map.values());

1
OP hỏi về cách chuyển đổi thành Danh sách <value>. Khi cung cấp câu trả lời, tốt hơn là bao gồm một Mô tả tốt với giải pháp được đề xuất. Câu hỏi này đã được chấp nhận trả lời.
HaveNoDisplayName

5

Nếu bạn muốn đảm bảo các giá trị trong kết quả List<Value>được sắp xếp theo thứ tự khóa của đầu vào Map<Key, Value>, bạn cần phải "đi qua" SortedMapbằng cách nào đó.

Hoặc bắt đầu với một bê tông SortedMapthực hiện (Chẳng hạn như TreeMap) hoặc chèn đầu vào của bạn Mapthành một SortedMaptrước khi chuyển đổi đó để List. ví dụ:

Map<Key,Value> map;
List<Value> list = new ArrayList<Value>( new TreeMap<Key Value>( map ));

Mặt khác, bạn sẽ nhận được bất cứ thứ tự bản địa nào mà việc Maptriển khai cung cấp, thường có thể là thứ gì đó không phải là thứ tự khóa tự nhiên (Hãy thử Hashtablehoặc ConcurrentHashMap, để đa dạng).


5
    Map<String, Integer> map = new HashMap<String, Integer>();
    map.put("java", 20);
    map.put("C++", 45);

    Set <Entry<String, Integer>> set = map.entrySet();

    List<Entry<String, Integer>> list = new ArrayList<Entry<String, Integer>>(set);

chúng ta có thể có cả cặp khóa và giá trị trong danh sách. Cũng có thể nhận khóa và giá trị bằng Map.Entry bằng cách lặp qua danh sách.


4
// you can use this
List<Value> list = new ArrayList<Value>(map.values());

// or you may use 
List<Value> list = new ArrayList<Value>();
for (Map.Entry<String, String> entry : map.entrySet())
{
list.add(entry.getValue());    
}

1
"Map<String , String > map = new HapshMap<String , String>;
 map.add("one","java");
 map.add("two" ,"spring");
 Set<Entry<String,String>> set =  map.entrySet();
 List<Entry<String , String>> list = new ArrayList<Entry<String , String>>    (set);
 for(Entry<String , String> entry : list ) {
   System.out.println(entry.getKey());
   System.out.println(entry.getValue());
 } "

1

Đây là phương pháp chung để lấy giá trị từ bản đồ.

public static <T> List<T> ValueListFromMap(HashMap<String, T> map) {
    List<T> thingList = new ArrayList<>();

    for (Map.Entry<String, T> entry : map.entrySet()) {
        thingList.add(entry.getValue());
    }

    return thingList;
}

1
HashMap<Integer, List<String>> map = new HashMap<>(); 
List<String> list = new ArrayList<String>();
list.add("Java");
list.add("Primefaces");
list.add("JSF");
map.put(1,list);
if(map != null){
    return new ArrayList<String>((Collection<? extends String>) map.values());
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.