什么接口表示具有插入顺序迭代的 LinkedHashSet

What interface represents a LinkedHashSet with insertion order iteration

由于以下代码行,我被 Sonar 拉了起来:

public void setFileNames(LinkedHashSet<String> fileNames) {

错误信息:

Avoid using implementation types like 'LinkedHashSet'; use the interface instead

当我想表示一个保持其插入顺序的未排序 Set 时,有什么解决方法?我是否只使用 Set 并明确表示将保留迭代顺序?

存储的数据将使用JaxB序列化,反序列化后迭代顺序是必不可少的。

(我知道并完全理解this

如果您需要对接收到的元素进行排序,那么您的方法应该接收一个列表而不是一个集合。但是为了摆脱警告,您必须使用 Set 而不是 LinkedHashSet。在您的方法中使用接口而不是实际的 类 是一种很好的做法。您不应该公开接口的实际实现。

此外,如果您只需要遍历 Set 的元素,您可以接收一个 Iterator,然后遍历它。

编辑:如果你真的想确保你只收到一个 LinkedHashSet,你可以这样做:

public void setFileNames(Set<String> fileNames) {
   if (!(fileNames instanceof LinkedHashSet)) {
      throw new IllegalArgumentException("I need a LinkedHashSet!");
   }
}

编辑 2:我不认为这里有一个理想的答案,但如果你真的需要最重要的是接收一个 LinkedHashSet,我会在界面中声明它并找到一种方法让 Sonar 忽略它该警告的具体实例。

我很欣赏其他答案,也很欣赏声纳警告。但是,有时(就像您的情况一样)可以忽略警告。在我看来,您正在使用 LinkedHashSet 来精确定义调用者的职责。 Set 不传达您的要求(订单未保留)。 List 也没有(不保证不同的元素)。所以也许可以忽略此警告。

另一种方法是您允许一个列表,然后您必须仔细检查(在您的方法内)该列表是否没有重复项,如果有则抛出异常。这对我来说似乎很可笑。

正如其他人所说,您应该弄清楚如何在 Sonar 中抑制警告。希望该机制有办法包含您抑制它的原因。然后你可以向未来的维护者解释你的决定。

没有这样的 interface,因为要求输入此行为毫无意义。代码 creating a Set 可能有关于顺序的意图并在创建 Set.

时选择适当的实现

但是如何才能问 Set 是否有插入顺序、字母顺序或任意顺序,例如基于散列,顺序对 setFileNames(Set<String> fileNames)?

这样的方法有影响

将参数类型声明为 Set 可以保证不会有对行为有影响的重复项,但插入顺序是无意义的信息(除非 caller 使它有意义)关于 Set.

的历史

如果你坚持要有一个方法签名setFileNames(LinkedHashSet<String> fileNames),我仍然可以传入一个Set没有意义的顺序,例如打电话
setFileNames(new LinkedHashSet<String>(hashSet)) 或具有字典顺序的集合,例如setFileNames(new LinkedHashSet<String>(treeSet))。你的签名只会让事情变得更复杂。

只接受一个Set,让调用者决定传入什么实现。

which keeps its insertion order?

这取决于来电者。 LinkedHashSet 保留基于插入的顺序,TreeSet 保留基于自然顺序的顺序。为什么你的方法要关心顺序是如何实现的?