为什么 Set.of() 如果元素是重复的,则抛出一个 IllegalArgumentException?

2022-09-02 00:20:14

在Java 9中,在Set接口上引入了新的静态工厂方法,称为of(),它接受多个元素,甚至是一个元素数组。

我想将列表转换为一个集合,以删除集合中的任何重复条目,这可以(在Java 9之前)使用以下命令完成:

Set<String> set = new HashSet<>();
set.addAll(list);

但我认为使用这个新的Java 9静态工厂方法会很酷:

Set.of(list.toArray())

其中 是先前定义的字符串列表。list

但是,唉,当元素是重复的时,java抛出了一个,在方法的Javadoc中也有说明。这是为什么呢?IllegalArgumentException

编辑:这个问题不是另一个关于概念上等效的主题Map.of()方法的问题的副本,而是明显不同的。并非所有静态工厂 of() 方法的行为都相同。换句话说,当我询问有关Set.of()方法的问题时,我不会点击涉及Map.of()方法的问题。


答案 1

Set.of()手动创建小的简短方法。在这种情况下,如果您为其提供重复的值,这将是一个公然的编程错误,因为您应该自己写出元素。即 这显然是程序员的错误。SetSet.of("foo", "bar", "baz", "foo");

很酷的方式实际上是一种非常糟糕的方式。如果要将 a 转换为 a ,可以使用 或 任何其他方式(例如使用流和收集)进行。优点包括不做无用的,自己的选择(你可能想要一个保持秩序)等。缺点包括必须键入更多的代码字符。ListSetSet<Foo> foo = new HashSet<>(myList);toSet()toArray()SetLinkedHashSet

和 方法(及其众多重载)背后的原始设计思想在这里进行了解释 Java 9 和此处的重载便利工厂集合方法的意义是什么,其中提到重点是小型集合,这是内部 API 中非常普遍的东西,因此可以具有性能优势。尽管目前委托给 varargs 方法的方法没有提供任何性能优势,但这可以很容易地改变(尽管不确定这是什么阻碍)。Set.of()List.of()Map.of()


答案 2

工厂方法为给定数量的元素生成不可变的 s。Set.of()Set

在支持固定数量参数(, , , 等)的变体中,没有重复项的要求更容易理解 - 当您调用方法时,您声明您希望创建一个正好3个元素的不可变元素,因此如果参数包含重复项,则拒绝输入而不是生成较小的输入是有意义的。static <E> Set<E> of​()static <E> Set<E> of​(E e1)static <E> Set<E> of​(E e1,E e2)Set.of(a,b,c)SetSet

虽然变体不同(如果允许创建任意数量的元素),但它遵循其他变体的相同逻辑。如果将元素传递给该方法,则表示希望创建完全不可变的元素,因此不允许重复。Set<E> of​(E... elements)SetnSetn

您仍然可以使用以下方法在单行中从 (具有潜在的重复项) 创建一个:SetList

Set<String> set = new HashSet<>(list);

这在Java 9之前就已经可用了。