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

时间:2015-02-06 14:18:29

标签: java sonarqube

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

public void setFileNames(LinkedHashSet<String> fileNames) {

显示错误消息:

  

避免使用'LinkedHashSet'等实现类型;改为使用界面

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

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

(我知道并完全理解this

4 个答案:

答案 0 :(得分:3)

没有这样的interface,因为输入需要这种行为是没有意义的。代码创建 Set可能有关于订单的意图,并在创建Set时选择适当的实现。

但是,如果Set是否具有插入顺序,字母顺序或任意,例如基于散列,顺序对像setFileNames(Set<String> fileNames)

这样的方法有所作为

将参数类型声明为Set可以保证不存在对行为产生影响的重复项,但是插入顺序是无意义的信息(除非调用者使其有意义)关于Set的历史。

如果您坚持使用方法签名setFileNames(LinkedHashSet<String> fileNames),我仍然可以通过无意义的顺序传递Set,例如调用
setFileNames(new LinkedHashSet<String>(hashSet))或具有字典顺序的集合,例如setFileNames(new LinkedHashSet<String>(treeSet))。你的签名只会让它变得更复杂。

答案 1 :(得分:1)

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

另一种方法是你允许一个List,然后你必须仔细检查(在你的方法中)列表没有重复,如果存在则抛出异常。这对我来说似乎很荒谬。

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

答案 2 :(得分:1)

只需接受Set,让调用者决定传入的实现。

  

保持其插入顺序?

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

答案 3 :(得分:-1)

如果您需要订购要接收的元素,那么您的方法应该接收List而不是Set。但是为了摆脱警告,你必须使用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忽略它的方法该警告的具体实例。