2017-11-02 13 views
6

Tôi gặp khó khăn khi tìm ra lý do tại sao findAny() ném ngoại lệ con trỏ null sau hoạt động filter() trên luồng. Trong trường hợp kiểm tra cụ thể này, hoạt động lọc nên lọc ra mọi thứ, không để lại kết quả nào cho findAny().Java stream findAny() gặp ngoại lệ con trỏ null sau khi lọc() hoạt động lọc ra mọi thứ

Optional<JsonNode> encryption = sseEncryptionList.stream() 
        .filter(n -> n.textValue().equals("AES256")) //Filters out everything 
        .findAny(); //Throws null pointer exception 

Các stack trace:

Exception in thread "main" java.lang.NullPointerException 
at example.Main.lambda$main$0(Main.java:41) 
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:174) 
at java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1351) 
at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126) 
at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:498) 
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485) 
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) 
at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152) 
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) 
at java.util.stream.ReferencePipeline.findAny(ReferencePipeline.java:469) 
at example.Main.main(Main.java:42) 

là hành vi mong đợi này cho findAny() để ném một con trỏ null nếu ngoại lệ dòng không chứa bất kỳ yếu tố?

Chỉnh sửa: Cách thanh lịch và chức năng để giải quyết các hoạt động lọc có thể lọc ra tất cả các yếu tố là gì?

+3

Bản sao có thể có của [Tại sao tìm thấy đầu tiên() ném NullPointerException nếu phần tử đầu tiên mà nó tìm thấy là null?] (https://stackoverflow.com/questions/32466799/why-does-findfirst-throw-a-nullpointerexception-if-the-first-element-it- find) – alfasin

+1

cũng nếu bạn muốn lọc nulls, chỉ cần sử dụng 'filter (Objects :: nonNull)' như tôi đã nói trong câu trả lời. – Eugene

Trả lời

4

Cách tốt nhất để tránh NPE là:

Optional<JsonNode> encryption = sseEncryptionList.stream() 
       .filter(Objects::nonNull) 
       .filter(n -> "AES256".equals(n.textValue())) 
       .findAny(); 

"AES256".equals(n.textValue())) sẽ không ném NPE nếu n.textValue() là null

2

Sự nhầm lẫn của bạn xuất phát từ thực tế là bạn filter trước tiên - và bạn mong đợi phương thức filter ở đâu đó trong theo dõi ngăn xếp; nhưng lưu ý rằng các hoạt động trung gian không làm gì cả, chúng được thực thi một cách lười biếng và chỉ khởi động khi có một hoạt động đầu cuối (chẳng hạn như findAny trong trường hợp của bạn). Nó thực sự là trong ngăn xếp dấu vết (số filter method), nhưng có vẻ như sau: Example.Main.lambda$main$0(Main.java:41).

Nếu bạn muốn lọc các giá trị null, đầu tiên cần làm:

.filter(Objects::nonNull) 
.filter(n -> n.textValue().equals("AES256")) 
.findAny() 
+1

Trên thực tế filter'ing lambda nằm trong stack trace ('at example.Main.lambda $ main $ 0 (Main.java:41)') - vì vậy ngoại lệ được ném vào đó. 'findAny' chỉ xảy ra là hàm ngoài cùng trong dấu vết. – Cthulhu

+0

@Cthulhu thx, đó là ý của tôi. khó thay đổi tã và trả lời SO :) sẽ chỉnh sửa ... – Eugene

+0

Điều gì xảy ra khi n.textValue() trả về null? –

0

Không, nó không phải là hành vi, khi dòng không chứa bất kỳ yếu tố. Trong trường hợp này, thay vào đó, nó trả về một Optional.empty().

Ngoài ra, NPE là nguyên nhân của một giá trị null trong dòng, như đã nêu trong javadocs:

Returns: 
an Optional describing some element of this stream, or an empty Optional if the stream is empty 

Throws: 
NullPointerException - if the element selected is null 
Các vấn đề liên quan