【问题标题】:How can I preserve insertion order in a HashSet?如何在 HashSet 中保留插入顺序?
【发布时间】:2018-12-10 10:24:10
【问题描述】:

我写了以下代码,

public int longestConsecutive(int[] nums) {
Set<Integer> num_set = new HashSet<Integer>();
for (int num : nums) {
    num_set.add(num);
    System.out.println("num_set: " + num_set.toString());
}

然后我有测试用例,

int[] nums  = {100, 4, 200, 1, 3, 2};

然后在最后一行输出中,控制台显示,

num_set: [1, 2, 3, 100, 4, 200]

我想知道为什么在添加操作之后之前的顺序被改变了。

【问题讨论】:

  • 使用考虑排序的TreeSet。在HashSet 中,检索时不考虑添加顺序,List 会这样做。如果您使用的是自定义类(您定义的类),那么您必须将您的类设为 ComparableComparator 类型。
  • 如果您希望对 Set 的整数进行排序,请使用 SortedSet。将您的行 Set&lt;Integer&gt; num_set = new HashSet&lt;Integer&gt;(); 更改为类似 `SortedSet numSet = new TreeSet();

标签: java set


【解决方案1】:

您似乎想保留插入顺序。为此有一个名为LinkedHashSet 的类。下面是一些示例代码:

int[] nums  = {100, 4, 200, 1, 3, 2};
Set<Integer> ints = new LinkedHashSet<>();
for(int i : nums) {
    ints.add(i);
}
System.out.println(ints);

上面的代码打印:[100, 4, 200, 1, 3, 2]

正如documentation 所说:

Set 接口的哈希表和链表实现,具有可预测的迭代顺序。此实现与 HashSet 的不同之处在于它维护一个双向链表,该列表贯穿其所有条目。这个链表定义了迭代顺序,也就是元素被插入集合(insertion-order)的顺序。请注意,如果将元素重新插入集合中,则插入顺序不会受到影响。 (如果在调用 s.contains(e) 将在调用之前立即返回 true 时调用 s.add(e),则元素 e 将重新插入集合 s。)

【讨论】:

    【解决方案2】:

    Glains 已经回答了您的问题。我还想补充一点:Java 库中有 interfaces,它为开发人员提供 contracts,承诺可以以何种方式使用它们。

    和你的问题一样,基本界面Set

    不包含重复元素的集合。

    还有你的implementorHashSet,它已经明确指出订单不能保证,在这种情况下,你应该期待任何与订单相关的承诺.

    它对集合的迭代order做出no保证;特别是,它不保证订单会随着时间的推移保持不变。

    具体来说,Java 提供了另一个接口 SortedSet 来确保您要求的顺序

    进一步提供对其元素的总排序的集合。元素使用其自然顺序进行排序,或者由通常在排序集创建时提供的 Comparator 进行排序。

    因此,在您的情况下,您应该找到一个实现接口 SortedSetimplementor,例如TreeSet

    通常我们不太关心实现细节,因为它们可以在我们不知情的情况下调整/更改,而另一方面,库开发人员在官方文档会一直保存。

    【讨论】:

      【解决方案3】:

      说明HashSet 文档

      它对集合的迭代顺序做出no保证;特别是,它不保证订单将保持恒定随着时间的推移

      如果您想使用保持自然顺序的Set,请改用SortedSet

      进一步提供对其元素的总排序的集合。元素使用其自然顺序进行排序,或者由通常在排序集创建时提供的 Comparator 进行排序。

      编辑: Set 确实没有说明其元素的顺序。例如,如果两个 Set 都包含相同的元素并且具有相同的大小,则它们是相等的。 Set 的迭代顺序取决于实现,并且可能在版本之间发生变化,因此您不应对其进行任何假设。它可能取决于#hashCode 的值,但也可能取决于插入顺序或将来的其他内容。但是,我们不应该在意,因为如果您这样做了,您应该使用 ListSortedSet

      【讨论】:

      • 为什么添加操作后之前的顺序变了?
      • @Vicky 还有什么不清楚的吗?否则,您可以将此标记为答案。
      猜你喜欢
      • 2010-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多