Java 初学问题

2022-07-17 10:02:38 +08:00
 Richard14

正在一边看书一边学 java ,学到集合的时候有两个问题:

1 、一般按照经验,hashmap 是使用频率最高的一种数据结构,大多数场景都能一把梭。java 中的 hashmap 内部实现是有序的吗?也就是如果我按顺序向 hashmap 添加 x,y,z ,能否保证后续遍历中也是按 xyz 的顺序获取?

2 、看书注意到 java 提供了很多相似的数据结构:Queue ,Stack ,Deque ,LinkedList 。功能各有限制,尤其是 queue 和 stack 把使用方式限定在很小的范围。逻辑上应该是被 deque 包含的,然后又被 LinkedList 包含,这是否意味着按照通常码农的使用经验倾向于用 LinkedList 表达所有,而不是专门为了特殊场景选一个功能非常有限的特殊数据类型?因为看起来比如如果使用 Queue 这个类万一需要获取列表长度都很麻烦

3300 次点击
所在节点    Java
21 条回复
taogen
2022-07-17 10:08:10 +08:00
倾向于使用 Stack Overflow
cmdOptionKana
2022-07-17 10:15:19 +08:00
> 比如如果使用 Queue 这个类万一需要获取列表长度都很麻烦

大多数情况下,事先看需求,当认为需求很稳定时就可以使用这些数据结构,好处是逻辑更清晰。
xingda920813
2022-07-17 10:16:32 +08:00
1, 不能保证按插入顺序遍历,如有需要请使用 LinkedHashMap 。如果需要总是按照一个有比较器提供的排序来遍历,请使用 TreeMap 或 ConcurrentSkipListMap 。
2, Stack 跟 Vector 一样是过时的集合,不要使用,他们也并不线程安全,尤其是 iterator() 方法返回的迭代器需要手动同步,否则有可能抛出 CME 。LinkedList 是链表,如果要数组实现的 Stack 的话,现代 Java 里面可以使用 ArrayDeque 来代替 Stack 。关于数组实现和链表实现,他们各有相应的特点,并不是总是使用链表的。
msg7086
2022-07-17 10:16:54 +08:00
1. LinkedHashMap 。

2. 选用能满足功能的最小功能集的数据结构。当然如果你做个人项目或者敏捷开发的话,随便怎么用都行。
Richard14
2022-07-17 10:22:56 +08:00
@xingda920813
@msg7086
无序倒不至于功能就做不出来了,只是按照个人经验,如果 hashmap 有序,通常来讲可以避免一些麻烦。LinkedHashMap 看名字好像是底层用链表实现的?这是否意味着随机读写性能很糟糕。。
luozic
2022-07-17 10:40:10 +08:00
benchmark 和对应场景的合适选择语言和库。

Premature optimization is the root of all evil. 过早优化是万恶之源。—— Donald Knuth 高德纳
thetbw
2022-07-17 11:31:19 +08:00
ArrayList 解决所有,没有什么事一个循环解决不了的,如果有,那就两个
Leviathann
2022-07-17 11:50:51 +08:00
1. LinkedHashMap 内部额外维护了插入的顺序
2. LinkedList.java 的作者发推问过有没有人用过这个,他说这东西是他写的,但是自己从来没用过。如果要表示 stack 可以直接用 arrayDeque
SeaTac
2022-07-17 11:52:12 +08:00
问题 1 其实看看 hashmap 的实现就知道了
简单的说 hashmap 是对 key 生成 hashcode 然后放到一个 array 里面,这样能实现 o(1) put & o(1) get
对 key 生成 hashcode 是无法保证排序的
linkedhashmap 更像是一个 fifo cache ,理论上来说没有随机性能的问题

不太懂为什么要问问题 2 ,用 linkedlist 表达所有在我看来是一种滥用
不过 queue ,stack 在我接触过的生产代码里很少见到,倒不是因为用 linked list 表达所有,只是因为没有使用的必要

至于你说的 queue 的长度,queue 本身是一个 linkedlist ,是有 queue.size()的
stack 也有 size
Richard14
2022-07-17 12:03:37 +08:00
@seaiaddca 感谢大佬回复,很清晰了。那我感觉我如果写业务代码会优先选用 linkedhashmap 这个结构一把梭,我觉得大多数场景我不在意它与 hashmap 的细节上的优化性能差距。如果我的数据结构本身有顺序处理的需要的话,我可以避免自己维护另外一个顺序表
book1925
2022-07-17 12:08:24 +08:00
@Leviathann

很好奇为啥 LinkedList 没人用啊。现在也在看面试题说 List 在大量数据下用 ArrayList 的增删操作新能比 LinkedList 性能好很多。但是从原理来说链表增删节点的开销不应该比数组要小吗😂
SeaTac
2022-07-17 12:36:37 +08:00
@book1925
看情况,我自己遇到用 list 的绝大多数情况是 create list 和 iterate / get element ,很少很少对 list element 进行删除或者插入(除了创建 list ),这个情况下用 arraylist 是合理的
SeaTac
2022-07-17 12:41:00 +08:00
@Richard14
原则是根据具体需要选择数据结构
如果没有多线程的问题,在对 map 的插入顺序有要求的情况下用 linkedhashmap 是合理的

当然你可以写个 load test 试一试,不过我觉得没必要…
FYFX
2022-07-17 13:53:05 +08:00
@book1925 写 LinkedList 的作者以前在推特上问过,他也很好奇谁在用 java 的 LinkedList 反正他自己是没用过,就这条推特:https://twitter.com/joshbloch/status/583813919019573248
Richard14
2022-07-17 14:14:23 +08:00
@seaiaddca 大佬建议多线程环境下用啥呢
SeaTac
2022-07-17 14:19:34 +08:00
@Richard14
我只用过 concurrenthashmap ,没遇到过需要对 key order 有要求的 multi thread 场景,你可能得自己查一查

随便搜了一个: https://stackoverflow.com/questions/28653889/java-thread-safe-linkedhashmap-implementation
Jooooooooo
2022-07-17 14:25:29 +08:00
1. 7 及以前是"有序的", 意思是你每次遍历它顺序一样(当然是什么顺序只有遍历过后才知道). 8 以后就乱序了(防止有人写程序依赖这个顺序). map 的定义里没有要求顺序, 所以你应该认为它是无序的.

2. 很多基础的类就是为了实现而实现的, java 作者就坦言过, 他自己也从来没有用过 linkedList, 都是 arraylist 一把梭.
Rocketer
2022-07-17 14:28:04 +08:00
hasmap 顾名思义是用 hash 实现的,学数据结构时老师都会让学生自己实现一个 hash 表,就彻底明白为什么不可能有序了
Dragonphy
2022-07-17 16:21:04 +08:00
V 站最近多了很多无聊的提问,明明搜一下就行的
https://www.bing.com/search?q=hashmap+%E6%98%AF%E6%9C%89%E5%BA%8F%E7%9A%84%E5%90%97
28Sv0ngQfIE7Yloe
2022-07-17 16:31:01 +08:00
打击下楼主的积极性,从我的角度看来

虽然你的提问一定程度上显示出你很「好学」很「认真」

但是这种学习方式感觉效率蛮低的

毕竟 google 一下或者 y2b 搜索下都能得到比楼上回复更易懂更详尽的回答(没有说楼上写的不好意思,只是随手写的很难比得上字字斟酌的文章 or 视频)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/866739

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX