Câu trả lời đơn giản
Trong Java 9 trở lên, sau khi List.of()
được thêm vào:
List<String> strings = List.of("foo", "bar", "baz");
Với Java 10 trở lên, điều này có thể được rút ngắn với var
từ khóa.
var strings = List.of("foo", "bar", "baz");
Điều này sẽ cung cấp cho bạn một bất biến List
, vì vậy nó không thể thay đổi.
Đó là những gì bạn muốn trong hầu hết các trường hợp bạn đang chuẩn bị nó.
Java 8 trở về trước:
List<String> strings = Arrays.asList("foo", "bar", "baz");
Điều này sẽ cung cấp cho bạn một List
hậu thuẫn bởi một mảng, vì vậy nó không thể thay đổi độ dài.
Nhưng bạn có thể gọi List.set
, vì vậy nó vẫn có thể thay đổi .
Bạn có thể thực hiện Arrays.asList
thậm chí ngắn hơn với nhập tĩnh:
List<String> strings = asList("foo", "bar", "baz");
Nhập tĩnh:
import static java.util.Arrays.asList;
Mà bất kỳ IDE hiện đại nào cũng sẽ gợi ý và tự động làm cho bạn.
Ví dụ trong IntelliJ IDEA bạn nhấn Alt+Enter
và chọn Static import method...
.
Tuy nhiên, tôi không khuyên bạn nên rút ngắn List.of
phương thức này of
, vì điều đó trở nên khó hiểu.
List.of
đã đủ ngắn và đọc tốt.
Sử dụng Stream
s
Tại sao nó phải là một List
?
Với Java 8 trở lên, bạn có thể sử dụng một Stream
cái linh hoạt hơn:
Stream<String> strings = Stream.of("foo", "bar", "baz");
Bạn có thể nối Stream
s:
Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
Stream.of("baz", "qux"));
Hoặc bạn có thể đi từ a Stream
đến a List
:
import static java.util.stream.Collectors.toList;
List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());
Nhưng tốt nhất, chỉ cần sử dụng Stream
mà không thu thập nó để a List
.
Nếu bạn thực sự cần mộtjava.util.ArrayList
(Bạn có thể không.)
Để trích dẫn JEP 269 (nhấn mạnh của tôi):
Có một tập hợp nhỏ các trường hợp sử dụng để khởi tạo một thể hiện bộ sưu tập có thể thay đổi với một bộ giá trị được xác định trước. Thông thường, nên để các giá trị được xác định trước đó nằm trong một bộ sưu tập không thay đổi và sau đó khởi tạo bộ sưu tập có thể thay đổi thông qua một hàm tạo sao chép.
Nếu bạn muốn cả hai chuẩn bị trước ArrayList
và thêm vào sau đó (tại sao?), Hãy sử dụng
ArrayList<String> strings = new ArrayList<>(List.of("foo", "bar"));
strings.add("baz");
hoặc trong Java 8 trở về trước:
ArrayList<String> strings = new ArrayList<>(asList("foo", "bar"));
strings.add("baz");
hoặc sử dụng Stream
:
import static java.util.stream.Collectors.toCollection;
ArrayList<String> strings = Stream.of("foo", "bar")
.collect(toCollection(ArrayList::new));
strings.add("baz");
Nhưng một lần nữa, tốt hơn là chỉ sử dụng Stream
trực tiếp thay vì thu thập nó cho a List
.
Chương trình để giao diện, không triển khai
Bạn nói rằng bạn đã khai báo danh sách dưới dạng ArrayList
mã trong mã của mình, nhưng bạn chỉ nên làm điều đó nếu bạn đang sử dụng một số thành viên ArrayList
không có trong đó List
.
Mà bạn rất có thể không làm.
Thông thường, bạn chỉ cần khai báo các biến bởi giao diện chung nhất mà bạn sẽ sử dụng (ví dụ Iterable
, Collection
hay List
), và khởi tạo chúng với việc thực hiện cụ thể (ví dụ ArrayList
, LinkedList
hoặc Arrays.asList()
).
Mặt khác, bạn giới hạn mã của mình vào loại cụ thể đó và sẽ khó thay đổi hơn khi bạn muốn.
Ví dụ: nếu bạn chuyển một ArrayList
đến void method(...)
:
// Iterable if you just need iteration, for (String s : strings):
void method(Iterable<String> strings) {
for (String s : strings) { ... }
}
// Collection if you also need .size(), .isEmpty(), or .stream():
void method(Collection<String> strings) {
if (!strings.isEmpty()) { strings.stream()... }
}
// List if you also need .get(index):
void method(List<String> strings) {
strings.get(...)
}
// Don't declare a specific list implementation
// unless you're sure you need it:
void method(ArrayList<String> strings) {
??? // You don't want to limit yourself to just ArrayList
}
Một ví dụ khác sẽ luôn luôn khai báo biến số InputStream
mặc dù nó thường là a FileInputStream
hoặc a BufferedInputStream
, bởi vì một ngày nào đó bạn hoặc ai đó sẽ muốn sử dụng một số loại khác InputStream
.
ArrasyList<String> places = ["Buenos Aires", "Córdoba", "La Plata"]