2009-08-06 24 views
35

Được cung cấp Danh sách sau:Trình trợ giúp để loại bỏ các tham chiếu null trong một Danh sách Java?

List<String> list = new ArrayList<String>(); 

list.add("s1"); 
list.add("s2"); 
list.add(null); 
list.add("s3"); 
list.add(null); 
list.add("s4"); 

Tôi cần lớp trợ giúp loại bỏ tham chiếu không có giá trị. Một cái gì đó như:

SomeHelper.removeNullReference (danh sách);

sao cho danh sách chỉ chứa "s1", "s2", "s4", "s4" (tham chiếu không null).

Tôi nên sử dụng thông tin gì để đáp ứng yêu cầu này?

Trả lời

103
list.removeAll(Collections.singleton(null)); 
+0

Tuyệt, tôi không biết về singletonList(). Đó là thanh lịch hơn ba lót của tôi. –

+4

Các lớp Collections và Array là các kho báu thực sự - và singletonList() cũng như emptyList() là những lý do chính tại sao sử dụng ArraList hoặc Vector làm kiểu tham số phương thức ở bất cứ đâu nên bị trừng phạt với ít nhất 20 dấu gạch ngang. –

+3

Nó cũng có thể là 'list.removeAll (Arrays.asList (null))', nhưng 'singletonList' hơi nhanh hơn. –

3

Nếu bạn có thể kiểm soát instantiation của List sau đó bạn có thể ngăn chặn sự null được bổ sung bằng cách viết một thực hiện tùy chỉnh List như:

public class NoNullsList<E> extends ArrayList<E> { 

    public void add(int index, E element) { 
    if (element != null) { 
     super.add(index, element); 
    } 
    } 

    public boolean add(E e) { 
    return e == null ? false : super.add(e); 
    } 
} 

AFAIK, bạn không cần phải ghi đè addAll vì việc triển khai ArrayList của chúng gọi là add.

List<String> list = new NoNullsList<String>(); 

list.add("s1"); 
list.add("s2"); 
list.add(null); 
list.add("s3"); 
list.add(null); 
list.add("s4"); 
+1

Cách tiếp cận tốt đẹp! (+1) –

+1

Các phương thức 'add' này vi phạm hợp đồng' List.add' (hoặc thực sự là Collection.add). Nếu bạn muốn cấm các phần tử null, hãy ném một ngoại lệ (như IllegalArgumentException) ở đó thay vì trả về 'false'. –

+1

@ PaŭloEbermann Khi bạn tạo một Class cho mục đích rõ ràng là bỏ qua null (không cho phép null như bạn có thể thấy từ OP), nó không có ý nghĩa gì khi ném một ngoại lệ trong trường hợp (được mong đợi) của một null được thêm vào . – Thor84no

3

Một nhược điểm của phương pháp Don là nó kéo dài từ ArrayList. Điều đó có thể đủ tốt cho bây giờ, nhưng điều gì sẽ xảy ra khi bạn muốn sử dụng một triển khai khác nhau List? Bạn có thể tạo ra một số NoNullsLinkedList và một số NoNullsCopyOnWriteArrayList, v.v. nhưng sau đó bạn kết thúc với một loạt các lớp nhỏ chỉ khác nhau trong mệnh đề extends của chúng. Nó có thể là tốt hơn để tạo ra một wrapper List mà không chấp nhận giá trị null. Ví dụ:

public class NonNullList<E> extends AbstractList<E> { 
    private final List<E> delegate; 

    public NonNullList(List<E> delegate) { 
    this.delegate = delegate; 
    } 

    @Override 
    public E get(int index) { 
    return delegate.get(index); 
    } 

    @Override 
    public int size() { 
    return delegate.size(); 
    } 

    @Override 
    public E set(int index, E element) { 
    return delegate.set(index, element); 
    } 

    @Override 
    public void add(int index, E element) { 
    if(element != null) { 
     delegate.add(index, element); 
    } 
    } 

    @Override 
    public E remove(int index) { 
    return delegate.remove(index); 
    } 
} 

Đó là mã, nhưng bây giờ bạn có thể linh hoạt chọn việc thực hiện List khi tạo đối tượng.

Một vấn đề có thể xảy ra là bạn vẫn có thể chèn null s vào đối tượng List cơ bản. Cách tiếp cận của Don không có cùng giới hạn.

+3

Cũng như câu trả lời của Don, lớp của bạn vi phạm hợp đồng 'List.add' (hoặc thực sự là' Collection.add'). Khi phương thức thêm trả về (đúng hoặc sai), phần tử phải được đảm bảo là một phần tử bằng phần tử được cung cấp mà phần tử của bạn không thực hiện. Thay vào đó, hãy ném ngoại lệ hoặc ít nhất là tài liệu nổi bật rằng bạn vi phạm hợp đồng. –

-2

removeAll không hoạt động đối với tôi. Thay vào đó, tôi tạo danh sách mới:

new ArrayList<E>(list); 

Đơn giản như vậy.

+2

Tuy nhiên, vẫn có các thành phần rỗng, vì vậy bạn sẽ phải loại bỏ chúng sau đó. –

4

Java 8 thêm Collection.removeIf(Predicate) mà loại bỏ tất cả các yếu tố phù hợp với vị, vì vậy bạn có thể loại bỏ tất cả các lần xuất hiện của null từ một danh sách (hoặc bất kỳ bộ sưu tập) với

list.removeIf(Objects::isNull); 

sử dụng java.util.Objects.isNull như một Predicate.

Bạn cũng có thể sử dụng .removeIf(x -> x == null) nếu muốn; the difference is very minor.

0

Tôi thực sự thích giải pháp ngắn gọn mới của Java 8, tôi tin rằng bạn nên sử dụng nó bất cứ khi nào có thể.

list.removeIf(Objects::isNull); 

Ở phía bên kia, nếu bạn đang tìm kiếm một thực hiện đơn giản để học cách nó có thể được thực hiện, chẳng hạn như một lớp helper mà trả về danh sách không null mới, bạn có thể có một cái nhìn tại các mã sau . Nó cũng có thể được thực hiện để chấp nhận các kiểu generic, vì mục đích đơn giản, tôi đã sử dụng cùng một kiểu collection (như trong câu hỏi) trong lớp helper.

package removenullrefdemo; 

import java.util.ArrayList; 
import java.util.List; 
import java.util.Objects; 

class ListHelper { 
    public static List<String> removeNullReference(List<String> list) { 
     List<String> newList = new ArrayList<>(); 

     list.forEach(item -> { 
      if (item != null) 
       newList.add(item); 
     }); 

     return newList; 
    } 
} 

public class Main { 
    public static void main(String[] args) { 
     List<String> list = new ArrayList<String>(); 

     list.add("s1"); 
     list.add("s2"); 
     list.add(null); 
     list.add("s3"); 
     list.add(null); 
     list.add("s4"); 

     println("Items:"); 
     list.forEach(item -> println(item)); 

     // Remove null refs 
     println("Items (after nulls removed):"); 
     boolean useJava8removeIf = false; 
     if (useJava8removeIf) { 
      println("Using Java8 removeIf method with predicate."); 
      list.removeIf(Objects::isNull); 
     } 
     else { 
      println("Using our own helper."); 
      list = ListHelper.removeNullReference(list); 
     } 

     list.forEach(item -> println(item)); 

    } 

    static void println(String msg) { 
     System.out.println(msg); 
    } 
} 
Các vấn đề liên quan