(JAVA)HashSet里面保存的数据怎么变成有顺序的了?
@tcxu 你好,想跟你请教个问题:
package jiu;
/**
*@ClassName HashSetDemo
*
* @Description 测试HashMapSet集合类
*
* @date 2014-3-3 上午8:45:26
*
*/
import java.util.HashSet;
public class HashSetDemo {
public static void main(String args[]) {
// 创建HashSet对象
HashSet<String> hs = new HashSet<String>();
// 加入元素到HastSet中
hs.add("B");
hs.add("A");
hs.add("D");
hs.add("E");
hs.add("C");
hs.add("F");
System.out.println(hs);
}
}
不是说HashSet是无序的吗?怎么输出结果却有序了?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
我记得现在jdk8 版本的hashSet底层是调用HaseMap 的K来实现无序的,无序的概念并不是说你输入什么都会打乱顺序,他会按照HashCode进行插入到Hash 中,最后会用hash表存的顺序输出!
hashSet的无序是指不能以写入的顺序或倒序输出
你对无序这个概念有误差啊
输出应当显示 26 行 (for 循环进行了 26 次),可你显示的输出共 27 行。最后一行 "[A, Z]"是多出来的、是不应当出现的(可能是你复制粘贴时的错误)。
回复
@tcxu : 看 [U, F] 这一行,就知道不是有序的
回复
就字符串比较而言,前5行,即 [A,Z] ... [E,V], 为升序, 从第6行[U,F]起,变为降序。....
回复
@tcxu : 一组总共就两个,比较升序降序没意义。总之,按顺序加入的,打印出来有升序,有降序,说明不是有序的
引用来自“wy65”的评论
可以把所有字母全部加入,然后在看看还是不是有序的
hash 是无须的,或者说是不保证有序的。
但多次重新运行下列代码,亦可看出:每个 Integer 元素的哈希值,就是它的整形数的值。而且 hashset 的输出结果都是进行排序了的,那hashset 是怎么做到对结果的有顺序输出的呢?
输出:
回答是: 虽然 hash 有它自己的顺序, 但这个顺序是hash的顺序.不一样的哈希算法,顺序也是不一样的。而且有序输出跟有序存储是两码事。
看来 正如 HashSet能对结果进行排序吗 的讨论指出的那样, "你需要百度下:数据结构、存储结构、还有hash键值对。总的来说你缺的太多,别一下直接想这么深的问题,先从数据结构开始学" 。
是的,HashSet 元素的存储(地址)是无序的。一般来讲,通过进行迭代的迭代器也是依次将各个元素(字符串),无序地输出。
楼主所示的"有序结果",其实是一种极其特殊案例:每个元素都仅是一(单)个字符,或都是数字字符,或都是小写英文字符,或都是大写英文字符。
元素的存储地址,视这个元素的哈希值而定。由于元素仅有一个字符,其哈希值的计算结果,就会是这个给定字符的 ascii 码(参见: 哈希算法)的值。结果, 打印出的 HashSet 列表,就会是貌似经过排序后的结果。但要注意构成这种案例的条件:元素必须 都是单个数字字符、或都是单个英文小写字符、或都是单个英文大写字符。
下列代码显示每个元素的哈希值,以及最终调用 toString() 输出 HashSet hs 的结果。输出结果显示,单个字符元素的哈希值,就是它的 ASCII值。
输出:
HashSet的原理是:计算对象的hash值,并映射到数组的下标。再看一下String的hashCode()方法的源码
哈希值是通过char对应的int值计算出来的,即:char对应的int值越大,hash值就越大。
而在拉丁字母A、B、C、D的char字符对应的int值恰巧是递增的,所以他们的hash值也恰巧是递增的,所以最终映射到HashSet内的数组的位置也是顺序的。
可以把所有字母全部加入,然后在看看还是不是有序的