2017-11-09 7 views
11

Set 인터페이스는 구현시 null 요소가 허용되는지 여부에 대해 약속하지 않습니다. 각 구현은 문서에서 이것을 선언해야합니다.Java의 Collectors.toSet()은 null을 허용 할 수 있습니까?

Collectors.toSet()Set의 구현을 반환 하겠지만 "명시 적으로"Set의 유형, 변경 가능성, serializability 또는 스레드 안전성에 대한 보장이 없음 "을 약속합니다. 무효 안전은 언급되지 않았다.

현재 OpenJDK의 Collectors.toSet() 구현은 null 요소를 허용하는 HashSet을 항상 사용하지만 향후 변경 될 수 있으며 다른 구현은 다르게 수행 될 수 있습니다. Set 구현 null 요소를 금지하는 경우

, 그것은 add(null)을 시도하는 동안 특히, 여러 번 NullPointerException가 발생합니다. Collectors.toSet()이 null-intolerant Set 구현을 사용하기로 결정한 경우 에 stream.collect(Collectors.toSet())을 호출하면 문제가되는 것으로 보입니다. collect의 사양에는 예외가 나열되어 있지 않으며 Collector 메서드 중 하나의 사양도 나와 있지 않습니다. 이것은 collect 호출이 stream 내에서 널을 허용한다는 것을 제안 할 수 있지만, 반면에 NullPointerException은 엄격히 나열 할 필요가 없으므로 이것이 실제로 많은 것을 의미하는지 명확하지 않습니다.

다른 곳에서는 더 명확하게 지정되어 있습니까? 특히 다음 코드는 던지지 않도록 보장됩니까? true을 돌려 주겠습니까? 그렇지 않으면

import java.util.stream.*; 

class Test { 
    public static boolean setContainsNull() { 
     return Stream.of("A", "list", "of", null, "strings") 
        .collect(Collectors.toSet()) 
        .contains(null); 
    } 
} 

, 그럼 나는 우리가 항상 스트림 Collectors.toSet()를 사용하거나 NullPointerException을 처리 할 준비가되기 전에 더 널 (null)을 포함하지 않는 확인해야합니다 가정합니다. (이 예외만으로도 충분합니까?) 또는 허용되지 않거나 어렵다면 Collectors.toCollection(HashSet::new)과 같은 코드를 사용하여 특정 세트 구현을 요청할 수 있습니다.

편집 :existing question 외면적으로 비슷하게 들리는이 질문은 그 것으로 추정되는 복제본으로 마감되었습니다. 그러나 링크 된 질문은 Collectors.toSet()을 전혀 다루지 않습니다. 또한, 그 질문에 대한 대답은 가정 질문 내 질문의 양식을 형성합니다. 그 질문은 묻습니다 : 스트림에 null이 허용됩니까? 예. 그러나 null을 포함하는 (완벽하게 허용되는) 스트림이 표준 수집기를 통해 수집되면 어떻게됩니까? null 지원 등 "형, 가변성, 직렬화, 또는 스레드 안전"과 underspecified 행동과 같은 의도적으로 지정되지 않은 행동의 차이는,이

+1

언급되지 않았지만 NULL을 허용하지 않으면 그다지 나쁜 형식이 아니며 아무 말도하지 않았다고 생각합니다. –

+2

@SleimanJneidi 당신이 링크 한 질문은 표준 수집가와 아무 관련이 없습니다. 이는 제가 묻고있는 것입니다. 스트림에 널 (null)을 포함 할 수 있는지 물어 봅니다. (질문은 당연한 것입니다.) 그리고 NPE를 피하기 위해 널을 포함하는 스트림에 명시 적으로 널 (null) 허용하지 않는 코드를 적용 할 수있는 마법이 있는지 여부를 묻습니다. 'collect (Collectors.toSet())'는 명시 적으로 null을 허용하지 않는 코드가 아닙니다. 그렇지 않으면 필자는 정확하게 그것이 맞는지 여부를 묻습니다. –

+0

지정하지 않았으므로 어느 쪽이든 추측하지 않습니다. null 값이 가능성이 있다는 것을 알고 있다면, 나는 항상 완전히 안전하기 위해'toCollection (HashSet :: new)'를 사용할 것입니다. – VGR

답변

4

.

동작이 명확하지 않을 때마다 참조 구현의 실제 동작은 호환성 제한으로 인해 원래의 의도를 방해하더라도 나중에 변경 될 수없는 사실이되거나, 강한 이유없이 변경 될 수있다.

진정한 불변 또는 비 직렬화 Set을 반환 할 예약 된 권한이 사용되지 않았지만 단순히 Java 8 릴리스에 그러한 유형이 존재하지 않았기 때문에 null이 아닌 경우에도 groupingBy이 금지 된 null 키를 금지하는 것처럼 적절한 해시 맵 유형입니다.

예를 들어, groupingBy 수집기는 구현 코드에서 null 키를 고의적으로 거부하지만 toMap은 실제 동작이 계약의 일부가되는 좋은 예입니다. Java 8에서 toMapnull 키를 허용하지만 null 값을 거부합니다. 이는 단순히 해당 동작이있는 Map.merge을 호출하기 때문입니다. It seems, this wasn’t an intended behavior in the first place. 이제 Java 9에서 병합 기능이없는 toMap 콜렉터는 Map.merge을 더 이상 사용하지 않고 (JDK-8040892, this answer 참조) 의도적으로 이전 버전과의 동작 호환이 가능하도록 콜렉터 코드의 null 값을 거부합니다. 단순히 null 동작이 의도적으로 지정되지 않았다고 말한 적이 없기 때문입니다.

그래서, Collectors.toSet() (마찬가지로 Collectors.toList())는 이제 두 가지 주요 자바 버전 null 값을 허용하고이 미래에 변경되지 않습니다 있는지 확인 조용 할 수 있도록 부여에 대해이 작업을하지해야한다는 말을 더 사양이 없다 .

+3

+1 Btw, 새로운 Java 10의 toUmodifiable 컬렉터는 null 값을 허용하지 않습니다. https://bugs.openjdk.java.net/browse/JDK-8184690을 참조하십시오. –