2011-04-05 39 views
165

Trong thực tế, nó là tốt hơn để trả về một danh sách trống như this:Collections.emptyList() vs dụ mới

return Collections.emptyList(); 

Hoặc như this:

return new ArrayList<Foo>(); 

Hoặc là điều này hoàn toàn phụ thuộc vào bạn sẽ làm gì với danh sách được trả về?

Trả lời

202

Sự khác biệt chính là Collections.emptyList() trả về một danh sách không thay đổi, tức là danh sách mà bạn không thể thêm thành phần.

Trong trường hợp hiếm hoi trong đó bạn làm muốn sửa đổi danh sách được trả về, do đó, đây không phải là tùy chọn.

Tôi muốn nói rằng việc trả lại danh sách không thay đổi là hoàn toàn tốt (và thậm chí là cách ưa thích) miễn là hợp đồng (tài liệu) không nói rõ một cách rõ ràng.


Bên cạnh đó, emptyList()might not create a new object with each call.

Triển khai các phương pháp này không cần phải tạo ra một đối tượng Danh sách riêng biệt cho mỗi cuộc gọi. Sử dụng phương pháp này có khả năng có chi phí so sánh để sử dụng trường được đặt tên tương tự. (Khác với phương pháp này, lĩnh vực này không cung cấp loại an toàn.)

Việc thực hiện emptyList trông như sau:

public static final <T> List<T> emptyList() { 
    return (List<T>) EMPTY_LIST; 
} 

Vì vậy, nếu phương pháp của bạn (mà trả về một danh sách trống) được gọi là rất thường xuyên , cách tiếp cận này thậm chí có thể cung cấp cho bạn hiệu suất tốt hơn một chút cả CPU và bộ nhớ khôn ngoan.

+3

Vì vậy, 'Collections.emptyList()' có phù hợp hơn để nói, kiểm tra lỗi và tương tự không? – mre

+3

Vâng, tôi sẽ nói như vậy. – aioobe

+1

Các máy khách API sẽ không nhận được 'NullPointerException' bằng cách trả về' Collections.emptyList() 'thay vì' null'. – realPK

24

Collections.emptyList là không thay đổi nên có sự khác biệt giữa hai phiên bản, do đó bạn phải xem xét người dùng của giá trị trả lại.

Trả lại new ArrayList<Foo> luôn tạo một đối tượng mới của đối tượng để nó có thêm chi phí rất nhỏ liên quan đến nó, có thể cung cấp cho bạn lý do để sử dụng Collections.emptyList. Tôi thích sử dụng emptyList chỉ vì nó dễ đọc hơn.

4

tôi sẽ đi với Collections.emptyList() nếu danh sách trả về không được sửa đổi trong bất kỳ cách nào (như danh sách là không thay đổi), nếu không tôi sẽ đi với tùy chọn 2.

Lợi ích của Collections.emptyList() là các trường hợp tĩnh cùng được trả về mỗi lần và do đó không có sự tạo ra cá thể xảy ra cho mỗi cuộc gọi.

40

Bắt đầu với Java 5.0 bạn có thể chỉ định loại phần tử trong container:

Collections.<Foo>emptyList() 

Tôi đồng tình với những câu trả lời khác mà đối với trường hợp bạn muốn quay trở lại một danh sách trống mà vẫn có sản phẩm nào, bạn nên sử dụng cách tiếp cận này.

+22

Bắt đầu với Java 7, bạn có thể để trình biên dịch suy ra tham số kiểu của lời gọi phương thức chung từ kiểu đích: 'Danh sách list = Collections.emptyList()' –

2

Sử dụng Collections.emptyList() nếu bạn muốn đảm bảo rằng danh sách trả về không bao giờ được sửa đổi.Đây là những gì được trả về trên gọi emptyList():

/** 
* The empty list (immutable). 
*/ 
public static final List EMPTY_LIST = new EmptyList(); 
+3

không có gì mới so với các câu trả lời trước đó, đúng không? – kleopatra

+0

Tôi đến đây để tìm hiểu xem liệu gọi là 'Collections.emptyList() 'có chi phí xây dựng hay không. Xem chi tiết triển khai (mặc dù có thể không giống nhau trên tất cả các JVM) xác nhận rằng nó không. @Atul, JVM này là từ đâu? – wjl

1

Những câu trả lời cho nhấn mạnh thực tế rằng emptyList() trả về một bất biến List nhưng không đưa ra giải pháp thay thế. Các Constructor ArrayList(int initialCapacity) trường hợp đặc biệt 0 để trở new ArrayList<>(0) thay vì new ArrayList<>() cũng có thể là một giải pháp khả thi:

/** 
* Shared empty array instance used for empty instances. 
*/ 
private static final Object[] EMPTY_ELEMENTDATA = {}; 

[...]

/** 
* Constructs an empty list with the specified initial capacity. 
* 
* @param initialCapacity the initial capacity of the list 
* @throws IllegalArgumentException if the specified initial capacity 
*   is negative 
*/ 
public ArrayList(int initialCapacity) { 
    if (initialCapacity > 0) { 
     this.elementData = new Object[initialCapacity]; 
    } else if (initialCapacity == 0) { 
     this.elementData = EMPTY_ELEMENTDATA; 
    } else { 
     throw new IllegalArgumentException("Illegal Capacity: "+ 
              initialCapacity); 
    } 
} 

(nguồn từ Java 1.8.0_72)

+0

Tôi không đồng ý với cách tiếp cận của bạn. Bạn tiết kiệm một chút bộ nhớ và CPU trên khởi tạo, nhưng nếu danh sách bạn quay trở lại bị thay đổi, bạn sẽ mất thời gian khi danh sách phân bổ lại một mảng mới. Nếu nhiều yếu tố được thêm vào danh sách theo thời gian, điều này có thể chồng chất thành nhiều nút cổ chai hiệu suất hơn do [tốc độ tăng trưởng chậm hơn nhiều] (http://grepcode.com/file/repository.grepcode.com/java /root/jdk/openjdk/6-b14/java/util/ArrayList.java#ArrayList.ensureCapacity%28int%29). Tôi thích gắn bó với quy ước của một danh sách trống không thể sửa đổi hoặc danh sách có thể sử dụng được, có thể sửa đổi được. –

+1

Vì tôi đã cố gắng nhấn mạnh với từ ngữ của mình (_might be viable_): tất cả phụ thuộc vào trường hợp sử dụng của bạn. Tôi thường sẽ _either_ trở về mutable _or_ unmutable Bộ sưu tập, không phải là một hỗn hợp tùy thuộc vào thời tiết họ đang có sản phẩm nào hay không. Và để chống lại "xác nhận quyền sở hữu chậm hơn nhiều": [this] (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/ArrayList.java# ArrayList.ensureCapacityInternal% 28int% 29) là triển khai hiện tại. –

+0

Oh người đàn ông, nhìn vào tôi trích dẫn JDK 2 phiên bản lớn trong ngày. Vì vậy, java8 tránh các nút cổ chai hoàn toàn bằng cách nhảy lên đến dung lượng mặc định từ một kích thước ban đầu của 0. Xin lỗi tôi đã rất sai. –

5

Hãy cẩn thận mặc dù. Nếu bạn sẽ trả về Collections.emptyList() và sau đó thử thực hiện một số thay đổi với nó như add() hoặc smth như thế, u sẽ có một UnsupportedOperationException()Collections.emptyList() trả về một đối tượng không thay đổi.

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