Chuyển đổi mảng thành danh sách trong Java


1028

Làm cách nào để chuyển đổi một mảng thành một danh sách trong Java?

Tôi đã sử dụng Arrays.asList()nhưng hành vi (và chữ ký) bằng cách nào đó đã thay đổi từ Java SE 1.4.2 (tài liệu hiện có trong kho lưu trữ) thành 8 và hầu hết các đoạn tôi tìm thấy trên web đều sử dụng hành vi 1.4.2.

Ví dụ:

int[] spam = new int[] { 1, 2, 3 };
Arrays.asList(spam)
  • trên 1.4.2 trả về một danh sách chứa các phần tử 1, 2, 3
  • trên 1.5.0+ trả về danh sách chứa spam mảng

Trong nhiều trường hợp, nó rất dễ bị phát hiện, nhưng đôi khi nó có thể bị trượt không được chú ý:

Assert.assertTrue(Arrays.asList(spam).indexOf(4) == -1);

20
Tôi nghĩ rằng ví dụ của bạn bị hỏng : Arrays.asList(new int[] { 1, 2, 3 }); chắc chắn không biên dịch trong Java 1.4.2, bởi vì một int[]không một Object[].
Joachim Sauer

1
Ồ, bạn có thể đúng. Tôi không có trình biên dịch Java 1.4.2 để kiểm tra ví dụ của mình trước khi đăng. Bây giờ, sau bình luận của bạn và câu trả lời của Joe, mọi thứ có ý nghĩa hơn nhiều.
Alexandru

1
Tôi nghĩ Autoboxing sẽ chuyển đổi từ lớp nguyên hàm sang lớp Integer. Bạn có thể làm cho các diễn viên tự trước và sau đó mã trên cho Arrays.asListhoạt động.
Tiếng ngựa

2
Stream.boxed () của Java 8 sẽ đảm nhiệm việc tự động hộp và có thể được sử dụng cho việc này. Xem câu trả lời của tôi dưới đây .
Ibrahim Arief

Câu trả lời:


1431

Trong ví dụ của bạn, đó là vì bạn không thể có Danh sách loại nguyên thủy. Nói cách khác, List<int>là không thể.

Tuy nhiên, bạn có thể có một lớp List<Integer>sử dụng Integerbao bọc intnguyên thủy. Chuyển đổi mảng của bạn đến một Listvới Arrays.asListphương pháp hữu ích.

Integer[] spam = new Integer[] { 1, 2, 3 };
List<Integer> list = Arrays.asList(spam);

Xem này chạy trực tiếp tại IdeOne.com .


112
Hoặc thậm chí đơn giản hơn: Arrays.asList (1, 2, 3);
Kong

45
Làm thế nào nó biết không tạo ra một List<Integer[]>?
Thomas Ahle

25
Thất bại trong Java 5+.
djechlin

6
@ThomasAhle Nó không tạo Danh sách <Integer []> nó tạo một đối tượng List <Integer>. Và nếu bạn muốn loại an toàn, bạn viết: Mảng. <Integer> asList (spam);
dùng1712376

6
@ThomasAhle Đó là một câu hỏi hay. Đoán nó chỉ là một quy tắc trong trình biên dịch java. Ví dụ, đoạn mã sau trả về Danh sách <Integer []> Integer[] integerArray1 = { 1 }; Integer[] integerArray2 = { 2 }; List<Integer[]> integerArrays = Arrays.asList(integerArray1, integerArray2);
Simon

167

Trong Java 8, bạn có thể sử dụng các luồng:

int[] spam = new int[] { 1, 2, 3 };
Arrays.stream(spam)
      .boxed()
      .collect(Collectors.toList());

Điều này là tốt, nhưng nó sẽ không làm việc cho boolean[]. Tôi đoán đó là vì nó dễ làm như vậy Boolean[]. Đó có lẽ là một giải pháp tốt hơn. Dù sao, đó là một trò chơi thú vị.
GlenPeterson

138

Nói về cách chuyển đổi, nó phụ thuộc vào lý do tại sao bạn cần của bạn List. Nếu bạn cần nó chỉ để đọc dữ liệu. OK ở đây bạn đi:

Integer[] values = { 1, 3, 7 };
List<Integer> list = Arrays.asList(values);

Nhưng sau đó nếu bạn làm một cái gì đó như thế này:

list.add(1);

bạn nhận được java.lang.UnsupportedOperationException. Vì vậy, đối với một số trường hợp, bạn thậm chí cần điều này:

Integer[] values = { 1, 3, 7 };
List<Integer> list = new ArrayList<Integer>(Arrays.asList(values));

Cách tiếp cận đầu tiên thực sự không chuyển đổi mảng nhưng 'đại diện' nó giống như một List. Nhưng mảng nằm dưới mui xe với tất cả các thuộc tính của nó như số phần tử cố định. Xin lưu ý bạn cần chỉ định loại khi xây dựng ArrayList.


1
"Bất biến" làm tôi bối rối một lúc. Bạn rõ ràng có thể thay đổi giá trị của mảng. Bạn không thể thay đổi kích thước của nó, tuy nhiên.
Tim Pohlmann

125

Vấn đề là các vararg đã được giới thiệu trong Java5 và thật không may, cũng Arrays.asList()bị quá tải với một phiên bản vararg. Vì vậy, Arrays.asList(spam)trình biên dịch Java5 được hiểu như là một tham số vararg của mảng int.

Vấn đề này được giải thích chi tiết hơn trong Hiệu quả Java lần 2, Chương 7, Mục 42.


4
Tôi hiểu những gì đã xảy ra, nhưng không phải tại sao nó không được ghi lại. Tôi đang tìm kiếm một giải pháp thay thế mà không cần thực hiện lại bánh xe.
Alexandru

2
@UsmanIsmail Kể từ Java 8, chúng tôi có thể sử dụng các luồng cho chuyển đổi này. Xem câu trả lời của tôi dưới đây .
Ibrahim Arief

109

Có vẻ hơi muộn nhưng đây là hai xu của tôi. Chúng ta không thể có List<int>như intmột kiểu nguyên thủy nên chúng ta chỉ có thể có List<Integer>.

Java 8 (mảng int)

int[] ints = new int[] {1,2,3,4,5};
List<Integer> list11 =Arrays.stream(ints).boxed().collect(Collectors.toList()); 

Java 8 trở xuống (mảng Integer)

Integer[] integers = new Integer[] {1,2,3,4,5};
List<Integer> list21 =  Arrays.asList(integers); // returns a fixed-size list backed by the specified array.
List<Integer> list22 = new ArrayList<>(Arrays.asList(integers)); // good
List<Integer> list23 = Arrays.stream(integers).collect(Collectors.toList()); //Java 8 only

Cần ArrayList và không List?

Trong trường hợp chúng tôi muốn triển khai cụ thể Liství dụ: ArrayListthì chúng tôi có thể sử dụng toCollectionnhư:

ArrayList<Integer> list24 = Arrays.stream(integers)
                          .collect(Collectors.toCollection(ArrayList::new));

Tại sao list21không thể được sửa đổi cấu trúc?

Khi chúng tôi sử dụng Arrays.asListkích thước của danh sách trả về là cố định vì danh sách được trả lại không phải java.util.ArrayList, nhưng một lớp tĩnh riêng được xác định bên trong java.util.Arrays. Vì vậy, nếu chúng ta thêm hoặc xóa các thành phần khỏi danh sách được trả về, một UnsupportedOperationExceptionsẽ được ném. Vì vậy, chúng ta nên đi với list22khi chúng ta muốn sửa đổi danh sách. Nếu chúng ta có Java8 thì chúng ta cũng có thể đi với list23.

Để rõ ràng list21có thể được sửa đổi theo nghĩa mà chúng ta có thể gọi list21.set(index,element)nhưng danh sách này có thể không được sửa đổi về mặt cấu trúc tức là không thể thêm hoặc xóa các thành phần khỏi danh sách. Bạn cũng có thể kiểm tra câu hỏi này .


Nếu chúng ta muốn một danh sách bất biến thì chúng ta có thể gói nó thành:

List<Integer> list 22 = Collections.unmodifiableList(Arrays.asList(integers));

Một điểm khác cần lưu ý là phương pháp Collections.unmodifiableList trả về một khung nhìn không thể thay đổi của danh sách đã chỉ định. Bộ sưu tập chế độ xem không thể thay đổi là một bộ sưu tập không thể thay đổi và cũng là chế độ xem trên bộ sưu tập sao lưu. Lưu ý rằng những thay đổi đối với bộ sưu tập sao lưu vẫn có thể xảy ra và nếu chúng xảy ra, chúng có thể được nhìn thấy qua chế độ xem không thể thay đổi.

Chúng ta có thể có một danh sách thực sự bất biến trong Java 9 và 10.

Danh sách thực sự bất biến

Java 9:

String[] objects = {"Apple", "Ball", "Cat"};
List<String> objectList = List.of(objects);

Java 10 (Danh sách thực sự bất biến) theo hai cách:

  1. List.copyOf(Arrays.asList(integers))
  2. Arrays.stream(integers).collect(Collectors.toUnmodifiableList());

Cũng kiểm tra câu trả lời này của tôi để biết thêm.


@BasilBourque Ý tôi là không thể sửa đổi cấu trúc của danh sách bằng cách thêm / xóa nhưng có thể thay đổi các thành phần.
akhil_mittal

Thật vậy, tôi đã thử một số mã và xác nhận rằng gọi List::addList::removethất bại với một danh sách được trả về bởi Arrays.asList. JavaDoc cho phương thức đó được viết kém và không rõ ràng về điểm này. Trong lần đọc thứ ba, tôi cho rằng cụm từ có kích thước cố định có nghĩa là người ta không thể thêm hoặc xóa các thành phần.
Basil Bourque


11

Gần đây tôi đã phải chuyển đổi một mảng thành Danh sách. Sau đó, chương trình đã lọc danh sách cố gắng xóa dữ liệu. Khi bạn sử dụng hàm Arrays.asList (mảng), bạn tạo một bộ sưu tập kích thước cố định: bạn không thể thêm cũng không xóa. Mục này giải thích vấn đề tốt hơn tôi có thể: Tại sao tôi nhận được UnsupportedOperationException khi cố gắng xóa phần tử khỏi Danh sách? .

Cuối cùng, tôi đã phải thực hiện chuyển đổi "thủ công":

    List<ListItem> items = new ArrayList<ListItem>();
    for (ListItem item: itemsArray) {
        items.add(item);
    }

Tôi cho rằng tôi có thể đã thêm chuyển đổi từ một mảng vào danh sách bằng cách sử dụng thao tác List.addAll (mục).


11
new ArrayList<ListItem>(Arrays.asList(itemsArray))cũng vậy
Marco13

1
@BradyZhu: Cấp câu trả lời ở trên không giải quyết được vấn đề của tôi với mảng kích thước cố định, nhưng về cơ bản, bạn đang nói RTFM ở đây, đây luôn là hình thức xấu. Vui lòng giải thích những gì sai với câu trả lời hoặc đừng bận tâm bình luận.
Steve Gelman

2
Các công cụ kiểm tra có thể hiển thị cảnh báo ở đây và bạn đã nêu tên lý do. Không cần phải sao chép các yếu tố bằng tay, sử dụng Collections.addAll(items, itemsArray)thay thế.
Darek Kay

Chỉ cần nhấn ngoại lệ này. Tôi sợ câu trả lời của Marco13 phải là câu trả lời đúng. Tôi có thể cần phải đi qua mã cả năm để sửa tất cả ngoại lệ "asList".

7

Sử dụng mảng

Đây là cách đơn giản nhất để chuyển đổi một mảng thành List. Tuy nhiên, nếu bạn cố gắng thêm một phần tử mới hoặc xóa phần tử hiện có khỏi danh sách, một phần tử UnsupportedOperationExceptionsẽ bị ném.

Integer[] existingArray = {1, 2, 3};
List<Integer> list1 = Arrays.asList(existingArray);
List<Integer> list2 = Arrays.asList(1, 2, 3);

// WARNING:
list2.add(1);     // Unsupported operation!
list2.remove(1);  // Unsupported operation!

Sử dụng ArrayList hoặc các triển khai danh sách khác

Bạn có thể sử dụng một forvòng lặp để thêm tất cả các phần tử của mảng vào một Listtriển khai, ví dụ ArrayList:

List<Integer> list = new ArrayList<>();
for (int i : new int[]{1, 2, 3}) {
  list.add(i);
}

Sử dụng API Stream trong Java 8

Bạn có thể biến mảng thành một luồng, sau đó thu thập luồng bằng các trình thu thập khác nhau: Trình thu thập mặc định trong Java 8 sử dụng ArrayListphía sau màn hình, nhưng bạn cũng có thể áp đặt triển khai ưa thích của mình.

List<Integer> list1, list2, list3;
list1 = Stream.of(1, 2, 3).collect(Collectors.toList());
list2 = Stream.of(1, 2, 3).collect(Collectors.toCollection(ArrayList::new));
list3 = Stream.of(1, 2, 3).collect(Collectors.toCollection(LinkedList::new));

Xem thêm:


6

Một cách giải quyết khác nếu bạn sử dụng apache commons-lang:

int[] spam = new int[] { 1, 2, 3 };
Arrays.asList(ArrayUtils.toObject(spam));

Trong đó ArrayUtils.toObject chuyển đổi int[]thànhInteger[]


5

bạn phải bỏ vào mảng

Arrays.asList((Object[]) array)

3
java: các loại không tương thích: int [] không thể được chuyển đổi thành java.lang.Object []
dVaffection

@dVaffection Sau đó chuyển sang int []. Phần quan trọng là để đúc thành một mảng.
Nebril

5

Lót:

List<Integer> list = Arrays.asList(new Integer[] {1, 2, 3, 4});

5

Trong Java 9, bạn có giải pháp thậm chí thanh lịch hơn bằng cách sử dụng các danh sách bất biến thông qua phương thức nhà máy tiện lợi mới List.of:

List<String> immutableList = List.of("one","two","three");

(không biết sao chép từ đây )


FYI, để tìm hiểu một số chi tiết kỹ thuật đằng sau điều này, hãy xem JEP 269: Phương pháp nhà máy tiện lợi cho bộ sưu tậpbài nói chuyện của Stuart Marks , tác giả chính.
Basil Bourque

5

Nếu bạn đang nhắm mục tiêu Java 8 (hoặc mới hơn), bạn có thể thử điều này:

int[] numbers = new int[] {1, 2, 3, 4};
List<Integer> integers = Arrays.stream(numbers)
                        .boxed().collect(Collectors.<Integer>toList());

GHI CHÚ:

Hãy chú ý đến Collectors.<Integer>toList(), phương pháp chung này giúp bạn tránh được lỗi "Loại không khớp: không thể chuyển đổi từ List<Object>thành List<Integer>".


4
  1. Sử dụng ổi:

    Integer[] array = { 1, 2, 3};
    List<Integer> list = Lists.newArrayList(sourceArray);
  2. Sử dụng Bộ sưu tập Apache Commons:

    Integer[] array = { 1, 2, 3};
    List<Integer> list = new ArrayList<>(6);
    CollectionUtils.addAll(list, array);

3

Nếu điều này có ích: Tôi đã có cùng một vấn đề và chỉ cần viết một hàm chung lấy một mảng và trả về một ArrayList cùng loại có cùng nội dung:

public static <T> ArrayList<T> ArrayToArrayList(T[] array) {
    ArrayList<T> list = new ArrayList<T>();
    for(T elmt : array) list.add(elmt);
    return list;
}

Điều gì nếu nó không giúp đỡ? Vậy thì bạn đã làm gì ?? ... jk :)
Sᴀᴍ vào

2

Mảng đã cho:

    int[] givenArray = {2,2,3,3,4,5};

Chuyển đổi mảng số nguyên sang Danh sách số nguyên

Một cách: boxed () -> trả về IntStream

    List<Integer> givenIntArray1 = Arrays.stream(givenArray)
                                  .boxed()
                                  .collect(Collectors.toList());

Cách thứ hai: ánh xạ từng phần tử của luồng vào Integer và sau đó thu thập

GHI CHÚ: Sử dụng mapToObj, bạn có thể chuyển đổi từng phần tử int thành luồng chuỗi, luồng char, v.v. bằng cách ghép i thành (char) i

    List<Integer> givenIntArray2 = Arrays.stream(givenArray)
                                         .mapToObj(i->i)
                                         .collect(Collectors.toList());

Chuyển đổi một loại mảng sang loại khác Ví dụ:

List<Character> givenIntArray2 = Arrays.stream(givenArray)
                                             .mapToObj(i->(char)i)
                                             .collect(Collectors.toList());

1

Vì vậy, nó phụ thuộc vào phiên bản Java nào bạn đang cố gắng-

Java 7

 Arrays.asList(1, 2, 3);

HOẶC LÀ

       final String arr[] = new String[] { "G", "E", "E", "K" };
       final List<String> initialList = new ArrayList<String>() {{
           add("C");
           add("O");
           add("D");
           add("I");
           add("N");
       }};

       // Elements of the array are appended at the end
       Collections.addAll(initialList, arr);

HOẶC LÀ

Integer[] arr = new Integer[] { 1, 2, 3 };
Arrays.asList(arr);

Trong Java 8

int[] num = new int[] {1, 2, 3};
List<Integer> list = Arrays.stream(num)
                        .boxed().collect(Collectors.<Integer>toList())

Tham khảo - http://www.codingeek.com/java/how-to-convert-array-to-list-in-java/


1

Bạn có thể cải thiện câu trả lời này được không vì đây là những gì tôi sử dụng nhưng tôi không rõ ràng 100%. Nó hoạt động tốt nhưng intelliJ đã thêm WeatherStation mới [0]. Tại sao là 0?

    public WeatherStation[] removeElementAtIndex(WeatherStation[] array, int index)
    {
        List<WeatherStation> list = new ArrayList<WeatherStation>(Arrays.asList(array));
        list.remove(index);
        return list.toArray(new WeatherStation[0]);
    }


Tại sao chúng ta nên cải thiện câu hỏi của bạn ? Hoặc bạn biết câu trả lời, hoặc bạn donet. Tất nhiên bạn nên cung cấp một câu trả lời thực sự giúp đỡ người khác, không phải là một câu hỏi gây nhầm lẫn nhiều hơn nó giúp.
HimBromBeere

-2

sử dụng hai dòng mã để chuyển đổi mảng thành danh sách nếu bạn sử dụng nó trong giá trị số nguyên, bạn phải sử dụng loại hộp tự động cho kiểu dữ liệu nguyên thủy

  Integer [] arr={1,2};
  Arrays.asList(arr);
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.