findFirst ()가 찾은 첫 번째 요소가 null 인 경우 NullPointerException이 발생하는 이유는 무엇입니까?
이것은 왜 던지는가 java.lang.NullPointerException
?
List<String> strings = new ArrayList<>();
strings.add(null);
strings.add("test");
String firstString = strings.stream()
.findFirst() // Exception thrown here
.orElse("StringWhenListIsEmpty");
//.orElse(null); // Changing the `orElse()` to avoid ambiguity
첫 번째 항목 strings
IS null
완벽하게 허용되는 값이다. 또한 s 를 처리 할 수 있는 것이 훨씬 더 의미 findFirst()
있는 Optional을 반환합니다 .findFirst()
null
편집 : orElse()
덜 모호하도록 업데이트했습니다 .
그 이유 Optional<T>
는 반환에 사용하기 때문입니다 . 선택 사항은을 포함 할 수 없습니다 null
. 기본적으로 "거기"와 "거기"로 설정되어있는 상황을 구분하는 방법을 제공하지 않습니다 null
.
이것이 문서null
가에서 선택 될 때 상황을 명시 적으로 금지하는 이유 입니다 findFirst()
.
던졌습니다 :
NullPointerException
-선택한 요소가null
마찬가지로 이미 논의 의 API 디자이너는 개발자가 치료를 원하는 가정하지 않는 null
값과없는 값 같은 방법으로.
그래도 그렇게하려면 시퀀스를 적용하여 명시 적으로 수행 할 수 있습니다.
.map(Optional::ofNullable).findFirst().flatMap(Function.identity())
스트림에. 첫 번째 요소가 없거나 첫 번째 요소가 인 경우 결과는 두 경우 모두 빈 선택 사항입니다 null
. 따라서 귀하의 경우에는
String firstString = strings.stream()
.map(Optional::ofNullable).findFirst().flatMap(Function.identity())
.orElse(null);
의 GET에 null
첫 번째 요소 중 하나 없거나 경우 값을 null
.
이러한 경우를 구별하려면 다음 flatMap
단계 를 생략하면됩니다 .
Optional<String> firstString = strings.stream()
.map(Optional::ofNullable).findFirst().orElse(null);
System.out.println(firstString==null? "no such element":
firstString.orElse("first element is null"));
이것은 업데이트 된 질문과 크게 다르지 않습니다. 당신은 교체해야 "no such element"
와 "StringWhenListIsEmpty"
와 "first element is null"
함께 null
. 그러나 조건문이 마음에 들지 않으면 다음과 같이 수행 할 수도 있습니다.
String firstString = strings.stream().skip(0)
.map(Optional::ofNullable).findFirst()
.orElseGet(()->Optional.of("StringWhenListIsEmpty"))
.orElse(null);
이제 firstString
이 될 것이다 null
요소가 존재하지만 경우 null
그것이 될 것입니다 "StringWhenListIsEmpty"
어떤 요소가 존재하지 않는 경우.
다음 코드을 대체 findFirst()
와 limit(1)
대체합니다 orElse()
과 reduce()
:
String firstString = strings.
stream().
limit(1).
reduce("StringWhenListIsEmpty", (first, second) -> second);
limit()
하나의 요소 만에 도달 할 수 있습니다 reduce
. BinaryOperator
에 전달 reduce
한 요소 또는 다른 그 반환 "StringWhenListIsEmpty"
에 요소가 도달하지 않는 경우 reduce
.
이 솔루션 Optional
의 BinaryOperator
장점은 할당되지 않고 람다가 아무것도 할당하지 않는다는 것입니다.
java.util.Objects.nonNull
찾기 전에 목록을 필터링하는 데 사용할 수 있습니다.
something like
list.stream().filter(Objects::nonNull).findFirst();
Optional is supposed to be a "value" type. (read the fine print in javadoc:) JVM could even replace all Optional<Foo>
with just Foo
, removing all boxing and unboxing costs. A null
Foo means an empty Optional<Foo>
.
It is a possible design to allow Optional with null value, without adding a boolean flag - just add a sentinel object. (could even use this
as sentinel; see Throwable.cause)
The decision that Optional cannot wrap null is not based on runtime cost. This was a hugely contended issue and you need to dig the mailing lists. The decision is not convincing to everybody.
In any case, since Optional cannot wrap null value, it pushes us in a corner in cases like findFirst
. They must have reasoned that null values are very rare (it was even considered that Stream should bar null values), therefore it is more convenient to throw exception on null values instead of on empty streams.
A workaround is to box null
, e.g.
class Box<T>
static Box<T> of(T value){ .. }
Optional<Box<String>> first = stream.map(Box::of).findFirst();
(They say the solution to every OOP problem is to introduce another type :)
'Programing' 카테고리의 다른 글
Google 스프레드 시트에서 맞춤 함수로 검색 한 데이터 새로 고침 (0) | 2020.10.17 |
---|---|
문자열 벡터에 대한 조인 연산자에 해당하는 것은 무엇입니까? (0) | 2020.10.17 |
`size_t`에 어떤 헤더를 포함해야합니까? (0) | 2020.10.17 |
Vim에서 삽입 모드로 들어 가지 않고 커서가있는 곳에 줄 바꿈을 삽입하려면 어떻게해야합니까? (0) | 2020.10.17 |
ifdef의 부울 : "#ifdef A && B"가 "#if defined (A) && defined (B)"와 동일합니까? (0) | 2020.10.17 |