为什么这段代码会按顺序打印出[1,2,3]?
Why does this code print out [1,2,3] in order?
对于这个问题,为什么它以特定顺序打印出 [1,2,3] 因为我认为 HashSets 没有排序,我会认为它打印出 [1,2,3] in 任何订单。我知道它消除了重复项。是不是因为这道题是从list -> HashSet -> list转换过来的?
import java.util.*;
class Try
{
public static void main(String args[]) {
List<Integer> list = new ArrayList<Integer>();
list.add(3);
list.add(3);
list.add(3);
list.add(2);
list.add(2);
list.add(1);
Set<Integer> set = new HashSet<Integer>(list);
List<Integer> list_1 = new ArrayList<Integer>(set);
System.out.println(list_1);
}
}
哈希集是无序的,这意味着当调用 new ArrayList<Integer>(set)
时,Java 编译器不保证结果列表是有序的。在您的情况下,碰巧它是按升序排列的,使用不同的 java 编译器编译,甚至在不同时间使用相同的 java 编译器可能会导致不同的排序。
例如,将您的代码稍微编辑为:
class Try {
public static void main(final String args[]) {
final List<Integer> list = new ArrayList<Integer>();
for (int i = 10; i > -10; i--) {
list.add(i);
}
final Set<Integer> set = new HashSet<Integer>(list);
final List<Integer> list_1 = new ArrayList<Integer>(set);
System.out.println(list_1);
}
}
我的机器上的输出结果为:
[0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, -8, 8, -9, 9, 10]
显然这是不对的。
因此,当将哈希集转换为列表时,假设结果具有某种顺序是不安全的
数字按其自然顺序排列有点偶然,但 List 元素的顺序由 Set 迭代其元素的顺序决定。
HashSet 没有定义迭代其元素的顺序,但它受每个元素的哈希码的影响。在 Integer
个对象的情况下,hashCode()
方法 returns 它自己的值。哈希码决定元素存储在哪个桶中,由于 HashSets 开始有 16 个桶,因此对值 1、2 和 3 的操作 i % 16
的剩余部分只是 1、2 和 3,所以这就是桶他们会进去的。对元素的迭代是一次完成的。每个桶中只有一个元素 - 桶 1 中有元素 1,依此类推。这就是它们按顺序排列的原因。
对于较大数量的整数,纯巧合将不适用,元素将按伪随机顺序排列,但实际上由每个元素的哈希码、当前桶数、精确度用于选择桶的算法以及最后添加元素的顺序 - 每个桶中都有一个元素列表(如果列表变得太大,则为 TreeSet)。
哈希集是无序的,这意味着当调用 new ArrayList(num) 时,Java 编译器不保证结果列表是有序的。在您的情况下,碰巧它是按升序排列的,使用不同的 java 编译器编译,甚至在不同时间使用相同的 java 编译器可能会导致不同的排序。
对于这个问题,为什么它以特定顺序打印出 [1,2,3] 因为我认为 HashSets 没有排序,我会认为它打印出 [1,2,3] in 任何订单。我知道它消除了重复项。是不是因为这道题是从list -> HashSet -> list转换过来的?
import java.util.*;
class Try
{
public static void main(String args[]) {
List<Integer> list = new ArrayList<Integer>();
list.add(3);
list.add(3);
list.add(3);
list.add(2);
list.add(2);
list.add(1);
Set<Integer> set = new HashSet<Integer>(list);
List<Integer> list_1 = new ArrayList<Integer>(set);
System.out.println(list_1);
}
}
哈希集是无序的,这意味着当调用 new ArrayList<Integer>(set)
时,Java 编译器不保证结果列表是有序的。在您的情况下,碰巧它是按升序排列的,使用不同的 java 编译器编译,甚至在不同时间使用相同的 java 编译器可能会导致不同的排序。
例如,将您的代码稍微编辑为:
class Try {
public static void main(final String args[]) {
final List<Integer> list = new ArrayList<Integer>();
for (int i = 10; i > -10; i--) {
list.add(i);
}
final Set<Integer> set = new HashSet<Integer>(list);
final List<Integer> list_1 = new ArrayList<Integer>(set);
System.out.println(list_1);
}
}
我的机器上的输出结果为:
[0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, -8, 8, -9, 9, 10]
显然这是不对的。
因此,当将哈希集转换为列表时,假设结果具有某种顺序是不安全的
数字按其自然顺序排列有点偶然,但 List 元素的顺序由 Set 迭代其元素的顺序决定。
HashSet 没有定义迭代其元素的顺序,但它受每个元素的哈希码的影响。在 Integer
个对象的情况下,hashCode()
方法 returns 它自己的值。哈希码决定元素存储在哪个桶中,由于 HashSets 开始有 16 个桶,因此对值 1、2 和 3 的操作 i % 16
的剩余部分只是 1、2 和 3,所以这就是桶他们会进去的。对元素的迭代是一次完成的。每个桶中只有一个元素 - 桶 1 中有元素 1,依此类推。这就是它们按顺序排列的原因。
对于较大数量的整数,纯巧合将不适用,元素将按伪随机顺序排列,但实际上由每个元素的哈希码、当前桶数、精确度用于选择桶的算法以及最后添加元素的顺序 - 每个桶中都有一个元素列表(如果列表变得太大,则为 TreeSet)。
哈希集是无序的,这意味着当调用 new ArrayList(num) 时,Java 编译器不保证结果列表是有序的。在您的情况下,碰巧它是按升序排列的,使用不同的 java 编译器编译,甚至在不同时间使用相同的 java 编译器可能会导致不同的排序。