当前位置: 首页 > 知识库问答 >
问题:

Java的collectors.toset()是否保证允许空值?

龚永新
2023-03-14

set接口不promise实现是否允许null元素。每个实现都应该在其文档中声明这一点。

collectors.toset()promise返回set的实现,但显式地“不保证返回的set的类型、可变性、可序列化或线程安全性”。空-没有提到安全。

OpenJDK中collectors.toset()的当前实现总是使用hashset,它允许空元素,但这在将来可能会发生变化,其他实现可能会做不同的操作。

如果set实现禁止null元素,则它会在不同时间抛出nullPointerException,特别是在尝试add(null)期间。如果collectors.toset()决定使用不容忍Null的set实现,那么对stream stream调用stream.collectors.toset())将引发。collect的规范没有列出任何异常,任何collector方法的规范也没有列出任何异常。这可能表明collection调用允许stream中有Null,但另一方面不清楚这实际上是否有什么意义,因为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)这样的代码请求特定的集合实现。

编辑:有一个问题表面上听起来很相似,而这个问题被认为是那个问题的重复。但是,链接的问题根本不针对collectors.toset()。此外,这个问题的答案构成了我的问题的基本假设。这个问题问:流中允许Null吗?是的。但是,当通过标准收集器收集包含Null的(完全允许的)流时,会发生什么呢?

共有1个答案

温成济
2023-03-14

故意未指定的行为(如“类型、可变性、可序列化或线程安全”)与未指定的行为(如null支持)之间存在区别。

每当一个行为没有被充分指定时,引用实现的实际行为往往会成为后来无法更改的事实,即使与最初的意图相悖,由于兼容性限制,或者至少在没有强有力的理由的情况下无法更改。

请注意,虽然没有使用返回真正不可变或不可序列化的set的保留权限,只是因为Java ;8版本上不存在此类类型,但即使没有足够的哈希映射类型,也可以强制执行非null行为,就像groupingby禁止null键一样,尽管也没有得到充分的指定。

进一步注意,虽然groupingby收集器故意拒绝其实现代码中的null键,但tomap是实际行为如何成为契约一部分的一个很好的示例。在Java ;8中,tomap允许null键,但拒绝null值,这仅仅是因为它调用具有该行为的map.merge。看来,这不是一个故意的行为。现在,在Java ;9中,没有合并函数的tomap收集器不再使用map.merge(JDK-8040892,另请参阅此答案),而是故意拒绝收集器代码中的null值,以便与以前的版本在行为上兼容。仅仅是因为从来没有说过null行为是故意不指定的。

因此,collectors.toset()(以及同样的collectors.tolist())现在允许两个主要Java版本的null值,并且没有规范说您不能想当然地认为这一点,因此您可以肯定这一点在将来不会改变。

 类似资料:
  • 问题内容: URI(特别是HTTP URL)是否允许包含一个或多个空格字符?如果 必须 对URL 进行编码,这是通常遵循的约定还是合法的选择? 特别是,有人可以指向RFC指出 必须 对带有空格的URL 进行编码吗? 提出问题的动机: 在对网站进行Beta测试时,我注意到某些URL的构造带有空格。Firefox似乎做对了,这让我感到惊讶!但是我希望能够将开发人员指向RFC,以便他们觉得有必要修复这些

  • 问题内容: 我想知道与使用if语句先检查null相比,使用try / exception处理null的成本。 提供更多信息。因为在此应用程序中,有> 50%的机会获得空值。如果未输入任何数据,则通常为null。因此,尝试使用null进行计算是很平常的事。 话虽这么说,如果我先使用if语句在计算之前先检查null并且不首先尝试计算是否会提高性能,或者仅抛出异常并对其进行处理会更便宜? 感谢您的任何建

  • 问题内容: 我真的是在这里指身份平等。 例如,以下内容将始终打印 true 吗? 问题答案: 是的,类令牌是唯一的(对于任何给定的类加载器而言)。 即,您将始终 在相同的类加载器领域中 获得对相同物理对象的引用。但是,不同的类加载器将加载不同的类令牌,同时,当两个不同的类加载器加载相同的类定义时,会将相同的类定义视为不同。

  • 问题内容: 我可以定义setter方法以返回此方法而不是void吗? 喜欢: 然后我可以使用新的ClassA()。setItem1()。setItem2() 问题答案: 关于JavaBeans规范有很多误解。 它存在的主要原因是统一的Java“组件”模型。这是一种使用反射与Java对象进行编程交互的方式。该API本身名为JavaBeans Introspection 。请看一下示例用法,您将比普通

  • 问题内容: 是否有办法像在Java中那样在PHP中使用* .properties文件?我想在属性或XML文件中存储一些应用程序级常量,并在我的代码中轻松地调用它们。非常感谢您的指导。谢谢。 问题答案: PHP可以使用原生加载和解析文件。 您还可以使用来在包含文件中设置常量。 如果您设置了XML,请研究PHP的XML功能。最简单的解决方案可能是使用SimpleXML。

  • 我希望正则表达式仅验证字母和空格。基本上这是为了验证全名。例如:史蒂夫柯林斯先生或史蒂夫柯林斯我尝试过这个正则表达式。“[a-zA-Z] \.?”但没有用。有人可以帮我吗 附言我使用Java。