a

Câu hỏi Tạo ArrayList từ mảng


Tôi có một mảng được khởi tạo như sau:

Element[] array = {new Element(1), new Element(2), new Element(3)};

Tôi muốn chuyển đổi mảng này thành một đối tượng của lớp ArrayList.

ArrayList<Element> arraylist = ???;

2967
2017-10-01 14:38


gốc


Trong Java9 -> List <String> list = List.of ("Hello", "World", "from", "Java"); - MarekM
@MarekM Câu trả lời này sai, vì điều này không trả về ArrayList. Poster yêu cầu cụ thể cho điều đó. - Tobias Weimer
Tôi nghĩ anh ấy không sử dụng giao diện List, vì đó là cách thực hành tốt nhất. Nhưng nếu bạn muốn ở đây là - ArrayList mới <> (List.of ("Xin chào", "Thế giới", "từ", "Java")); - MarekM
Vấn đề không phải là về việc sử dụng giao diện, vấn đề là trong giải pháp của bạn, danh sách trả về là không thể sửa đổi được. Đó có thể là một vấn đề, và lý do tại sao anh ta yêu cầu một ArrayList - Tobias Weimer


Các câu trả lời:


new ArrayList<>(Arrays.asList(array))

3971
2017-10-01 14:39



Vâng. Và trong trường hợp (phổ biến nhất) mà bạn chỉ muốn một danh sách, new ArrayList cuộc gọi là không cần thiết là tốt. - Calum
@Luron - chỉ cần sử dụng List<ClassName> list = Arrays.asList(array) - Pool
@Calum và @Pool - như đã nêu dưới đây trong câu trả lời của Alex Miller, sử dụng Arrays.asList(array) mà không chuyển nó vào một ArrayList đối tượng sẽ sửa kích thước của danh sách. Một trong những lý do phổ biến hơn để sử dụng ArrayList là có thể tự động thay đổi kích thước của nó và đề xuất của bạn sẽ ngăn chặn điều này. - Code Jockey
Arrays.asList () là một hàm khủng khiếp, và bạn không bao giờ nên sử dụng giá trị trả về của nó như là. Nó phá vỡ mẫu danh sách, vì vậy luôn luôn sử dụng nó trong biểu mẫu được chỉ ra ở đây, ngay cả khi nó có vẻ dư thừa. Câu trả lời tốt. - Adam
@Adam Hãy nghiên cứu javadoc cho java.util.List. Hợp đồng cho phép thêm cho phép họ ném một UnsupportedOperationException. docs.oracle.com/javase/7/docs/api/java/util/…  Phải thừa nhận rằng, từ quan điểm hướng đối tượng, nó không phải là rất hay mà nhiều lần bạn phải biết việc thực hiện cụ thể để sử dụng một bộ sưu tập - đây là một lựa chọn thiết kế thực dụng để giữ cho khung công tác đơn giản. - lbalazscs


Được:

Element[] array = new Element[] { new Element(1), new Element(2), new Element(3) };

Câu trả lời đơn giản nhất là:

List<Element> list = Arrays.asList(array);

Điều này sẽ làm việc tốt. Nhưng một số hãy cẩn thận:

  1. Danh sách được trả về từ asList có kích thước cố định. Vì vậy, nếu bạn muốn có thể thêm hoặc xóa các phần tử khỏi danh sách được trả về trong mã của mình, bạn sẽ cần phải bọc nó trong một ArrayList. Nếu không, bạn sẽ nhận được UnsupportedOperationException.
  2. Danh sách được trả lại từ asList() được hỗ trợ bởi mảng ban đầu. Nếu bạn sửa đổi mảng ban đầu, danh sách cũng sẽ được sửa đổi. Điều này có thể gây ngạc nhiên.

775
2017-10-01 15:39



Độ phức tạp của cả hai hoạt động là gì? Tôi có nghĩa là có và không sử dụng xây dựng danh sách mảng rõ ràng. - damned
Arrays.asList () chỉ đơn thuần tạo ra một ArrayList bằng cách gói mảng hiện có để nó là O (1). - Alex Miller
Gói trong một ArrayList mới () sẽ làm cho tất cả các phần tử của danh sách kích thước cố định được lặp lại và được thêm vào ArrayList mới như vậy là O (n). - Alex Miller
việc thực hiện Danh sách được trả về bởi asList () không thực hiện một số phương thức của Danh sách (như add (), remove (), clear (), etc ...) giải thích UnsupportedOperationException. chắc chắn là một caveat ... - sethro
Khi câu hỏi yêu cầu "một đối tượng của lớp ArrayList" Tôi nghĩ rằng nó là hợp lý để giả định các lớp nó đề cập đến là java.util.ArrayList. Arrays.asList thực sự trả về một java.util.Arrays.ArrayList mà không phải là instanceof lớp khác. Vì vậy, một báo trước thứ ba là nếu bạn cố gắng sử dụng nó trong một bối cảnh yêu cầu ở trên nó sẽ không hoạt động. - Dave L.


(chủ đề cũ, nhưng chỉ 2 xu là không đề cập đến ổi hoặc libs khác và một số chi tiết khác)

Nếu bạn có thể, hãy sử dụng ổi

Đó là giá trị chỉ ra cách ổi, mà đơn giản hóa rất nhiều những shenanigans:

Sử dụng

Đối với một danh sách không thể thay đổi

Sử dụng ImmutableList lớp và của nó of() và copyOf() phương pháp nhà máy (các phần tử không thể rỗng):

List<String> il = ImmutableList.of("string", "elements");  // from varargs
List<String> il = ImmutableList.copyOf(aStringArray);      // from array

Đối với danh sách có thể thay đổi

Sử dụng Lists lớp và của nó newArrayList() phương pháp nhà máy:

List<String> l1 = Lists.newArrayList(anotherListOrCollection);    // from collection
List<String> l2 = Lists.newArrayList(aStringArray);               // from array
List<String> l3 = Lists.newArrayList("or", "string", "elements"); // from varargs

Cũng xin lưu ý các phương pháp tương tự cho các cấu trúc dữ liệu khác trong các lớp khác, ví dụ trong Sets.

Tại sao lại là ổi?

Điểm thu hút chính có thể là để giảm sự lộn xộn do generics cho loại an toàn, như việc sử dụng của ổi phương pháp nhà máy cho phép các loại được phỏng đoán phần lớn thời gian. Tuy nhiên, đối số này giữ ít nước hơn khi Java 7 đến với toán tử kim cương mới.

Nhưng nó không phải là lý do duy nhất (và Java 7 không phải là ở khắp mọi nơi): cú pháp viết tắt cũng rất tiện dụng, và các phương thức khởi tạo, như đã thấy ở trên, cho phép viết mã biểu cảm hơn. Bạn làm trong một cuộc gọi Guava những gì cần 2 với Bộ sưu tập Java hiện tại.


Nếu bạn không thể ...

Đối với một danh sách không thể thay đổi

Sử dụng JDK Arrays lớp và của nó asList() phương pháp nhà máy, bọc bằng một Collections.unmodifiableList():

List<String> l1 = Collections.unmodifiableList(Arrays.asList(anArrayOfElements));
List<String> l2 = Collections.unmodifiableList(Arrays.asList("element1", "element2"));

Lưu ý rằng kiểu trả về cho asList() là một List sử dụng bê tông ArrayList thực hiện, nhưng không phải vậy  java.util.ArrayList. Đó là một loại bên trong, mô phỏng một ArrayList nhưng thực sự trực tiếp tham khảo mảng đã truyền và làm cho nó "ghi thông qua" (sửa đổi được phản ánh trong mảng).

Nó cấm sửa đổi thông qua một số List Phương pháp của API bằng cách đơn giản mở rộng AbstractList (do đó, việc thêm hoặc xóa các phần tử không được hỗ trợ), tuy nhiên nó cho phép các cuộc gọi đến set() để ghi đè lên các phần tử. Do đó danh sách này không thực sự bất biến và một cuộc gọi đến asList() nên được bọc bằng Collections.unmodifiableList().

Xem bước tiếp theo nếu bạn cần danh sách có thể thay đổi.

Đối với danh sách có thể thay đổi

Tương tự như trên, nhưng được bọc bằng thực tế java.util.ArrayList:

List<String> l1  = new ArrayList<String>(Arrays.asList(array));    // Java 1.5 to 1.6
List<String> l1b = new ArrayList<>(Arrays.asList(array));          // Java 1.7+
List<String> l2  = new ArrayList<String>(Arrays.asList("a", "b")); // Java 1.5 to 1.6
List<String> l2b = new ArrayList<>(Arrays.asList("a", "b"));       // Java 1.7+

Đối với mục đích giáo dục: The Good ol 'Manual Way

// for Java 1.5+
static <T> List<T> arrayToList(final T[] array) {
  final List<T> l = new ArrayList<T>(array.length);

  for (final T s : array) {
    l.add(s);
  }
  return (l);
}

// for Java < 1.5 (no generics, no compile-time type-safety, boo!)
static List arrayToList(final Object[] array) {
  final List l = new ArrayList(array.length);

  for (int i = 0; i < array.length; i++) {
    l.add(array[i]);
  }
  return (l);
}

295
2017-11-16 17:16



+1 Nhưng lưu ý rằng List được trả lại bởi Arrays.asList có thể thay đổi trong đó bạn vẫn có thể set các yếu tố - nó không thể thay đổi kích thước. Đối với danh sách không thể thay đổi mà không có ổi, bạn có thể đề cập Collections.unmodifiableList. - Paul Bellora
@haylem Trong phần của bạn Đối với mục đích giáo dục: The Good ol 'Manual Way, của bạn arrayToList cho Java 1.5+ không chính xác. Bạn đang instanciating danh sách Stringvà cố gắng truy xuất chuỗi từ mảng đã cho, thay vì sử dụng loại thông số chung, T. Ngoài ra, câu trả lời hay và +1 là người duy nhất bao gồm cả cách thủ công. - afsantos


Vì câu hỏi này khá cũ nên tôi ngạc nhiên rằng không ai đề xuất hình thức đơn giản nhất:

List<Element> arraylist = Arrays.asList(new Element(1), new Element(2), new Element(3));

Kể từ Java 5, Arrays.asList() có tham số varargs và bạn không phải xây dựng mảng một cách rõ ràng.


203
2018-06-22 11:30



Đặc biệt, List<String> a = Arrays.asList("first","second","third") - 18446744073709551615


new ArrayList<T>(Arrays.asList(myArray));

Đảm bảo rằng myArray có cùng loại với T. Bạn sẽ gặp lỗi trình biên dịch nếu bạn cố tạo List<Integer>từ một mảng int, ví dụ.


172
2017-10-01 14:40





Một cách khác (mặc dù về cơ bản tương đương với new ArrayList(Arrays.asList(array)) giải pháp hiệu suất-khôn ngoan:

Collections.addAll(arraylist, array);

77
2018-04-03 23:20





Bạn có thể chỉ cần một danh sách, không phải là một ArrayList. Trong trường hợp đó bạn chỉ có thể làm:

List<Element> arraylist = Arrays.asList(array);

62
2017-10-01 14:45



Điều đó sẽ được hỗ trợ bởi mảng đầu vào ban đầu, đó là lý do tại sao bạn (có thể) muốn bọc nó trong một ArrayList mới. - Bill the Lizard
Hãy cẩn thận với giải pháp này. Nếu bạn nhìn, các mảng KHÔNG trả về một java.util.ArrayList đúng. Nó trả về một lớp bên trong thực hiện các phương thức cần thiết, nhưng bạn không thể thay đổi các memebers trong danh sách. Nó chỉ đơn thuần là một trình bao bọc xung quanh một mảng. - Mikezx6r
Bạn có thể chuyển mục List <Element> thành một ArrayList <Element> - monksy
@ Mikezx6r: ít điều chỉnh: đó là danh sách kích thước cố định. Bạn có thể thay đổi các yếu tố của danh sách (set phương pháp), bạn không thể thay đổi kích thước của danh sách (không add hoặc là remove yếu tố)! - Carlos Heuberger
Có, với báo trước rằng nó phụ thuộc vào những gì bạn muốn làm với danh sách. Điều đáng chú ý là nếu OP chỉ đơn giản muốn lặp qua các phần tử, mảng không cần phải chuyển đổi chút nào. - PaulMurrayCbr