一、集合
1、什么是集合?
在 Java 中,集合/容器是指主要用途为存储其他元素的集合的类。你已经知道其中一个类:ArrayList。
2、集合的分类
在 Java 中,集合分为三个主要群组:集 (Set)、列表 (List)、映射 (Map)。
(1)集
想象扔在一起的一堆鞋子。这就是一个集。你可以向集中添加元素,也可以搜索或删除元素。需要注意的重要一点是,集元素没有特定的分配顺序。
(2)列表
现在想象一下,同一堆鞋子沿着墙壁整齐地排列。现在就有顺序了。每个元素都有自己的编号。你可以简单地根据编号(索引)找到第 4 双鞋。这就是一个列表。你可以将元素添加到列表的开头或中间位置,也可以删除元素 – 只需使用其索引即可。
(3)映射
想象一下同样的鞋子,但现在每双鞋都有一个名字注释:‘尼克’、‘维克’或‘安娜’。这就是一个映射(通常也称为词典)。每个元素都有自己的唯一名称,用于处理该元素。每个元素的唯一名称通常称为‘键’。因此,映射是一组键-值对。键不必是字符串:它可以是任意类型。键为 Integer 的映射实际上是列表(有点区别)。
3、集合元素的处理--迭代器
列表的元素有固定的顺序,因此可以只使用索引来显示它们。而集和映射则没有特定顺序,在删除项目或添加新项目时,它们的元素顺序可以改变。
因此发明了名为迭代器的特殊对象来处理集合元素。迭代器允许你浏览集合中的所有元素,即使它们只有名称而不是索引(映射),或者既没有名称也没有索引(集)。
我们从集合中获取一个特殊对象,即迭代器。迭代器只有两种方法。
(1)next() 方法返回集合中的下一个元素。
(2)hasNext() 方法检查是否仍存在 next() 未返回的元素。
(3)Java 有用于处理迭代器的简写符号。按照 while 和 for 的模式,又添加了一个特殊声明:for each。也可以使用关键字 for 来表示。
for-each 语句只用于处理集合和容器。它隐式地使用迭代器,但我们只看到返回的元素。
二、Date类型
1、这种类型存储日期和时间,也可以测量时间间隔。
2、存储形式:自格林威治标准时间 1970 年 1 月 1 日以来的毫秒数。
这个数字太大,以至于 int 中没有足够的空间容纳它,因此必须将其存储在 long 中。但是,计算任意两个日期之间的差值非常方便。只需执行减法即可得到精确到毫秒的差值。它还解决了日期变更线和夏令时的问题。
最有趣的部分是,每个对象在创建时都以当前时间进行初始化。要知道当前时间,只需创建一个 Date 对象。
3、使用:
getTime()
方法返回 Date 对象中存储的毫秒数。
after()
方法检查调用该方法的日期是否在传递给该方法的日期之后
getHours()、getMinutes()、getSeconds()
方法分别为调用它们的对象返回小时数、分钟数和秒数。
此外,在最后一个示例中,你会发现可以更改存储在 Date 对象中的日期/时间。”我们获取当前的时间和日期,然后将小时、分钟和秒重置为 0。我们还将一月设置为月份,将 1 设置为月份的日期。因此,yearStartTime
对象存储当年 1 月 1 日的日期和时间 00:00:00。之后,我们再次获取当前日期 (currentTime
),计算两个日期之间的差值(以毫秒表示),并将其存储在 msTimeDifference
中。然后将 msTimeDifference
除以 24 小时内的毫秒数,得出自今年年初到今天的完整天数。
三、ArrayList 和 LinkedList
集合可以通过不同的方式实现,没有一种实现始终是完美的。在一种方法中,某些操作的速度很快,而另一些操作的速度却很慢。在另一种方法中,情况可能恰恰相反。没有完美的通用型解决方法。因此,我们决定实现同一集合的多个版本。每个实现应针对一小组特定的操作进行优化。不同的集合就是这样产生的。以ArrayList 和 LinkedList为例。
在内部,ArrayList 是作为普通数组实现的。因此,在中间插入元素要求我们首先将所有后续元素移动一个位置,然后将新元素放入空闲插槽。获取和设置元素(get、set)的速度很快,因为这些操作只是处理相关的数组元素。
LinkedList 具有不同的内部结构(双向链表)。它是作为包含相互关联元素的列表实现的:一组不同的元素,每个元素存储对列表中下一个和上一个元素的引用。要将元素插入此类列表的中间位置,只需更改其未来邻近元素的引用即可。但是,要获取第 130 个元素,必须从 0 到 130 遍历每个对象。换句话说,get 和 set 操作的速度会很慢。
使用原则:如果经常要在集合中间插入(或删除)元素,最好使用 LinkedList。在所有其他情况下,ArrayList 更适用。
ArrayList:
虽然我们没有指定ArrayList的大小,但是底层是分配了数组的大小的,其默认大小为10。
每次在指定位置新插入的时候,其实是从插入位置开始每个元素右移一位。也就是我们在位置1插入实际是将位置3的元素复制到位置4,将元素2复制到位置3,将元素1复制到位置2。
当数组不够了的时候,会进行扩展,通常是当前长度的1.5倍+1(例如,默认是10,增加之后数
组长度是16)
set()
addAll()
四、可以对集和映射执行的操作
集是一组未编号的对象。
集的主要特征是它只包含唯一的对象,即,集的每个元素都不相同。
下面是可以对集执行的操作:
映射是由对组成的集合。
跟集相似,但它是一组键值对而不是唯一的元素。唯一的限制在于每个 «键» 必须是唯一的。映射不能包含具有相同键的两个对。
下面是可以对映射执行的操作:
遍历map:
五、Collections class
涉及集合的最常见操作已经在特殊的静态Collections中实现。
常用方法:
sort()
Java Collections sort()
min()
max()
reverse()反转列表
shuffle()函数把数组中的元素按随机顺序重新排列。想洗牌一样。
unmodifiableList()它从作为参数传递的列表中创建一个不可变列表。无法在此列表中添加或删除项目。Collections.unmodifiableList()的使用与场景
swap()交换元素
disjoint()检查两个集合是否相交,即它们是否至少有一个相同的元素。
六、HashMap
create:
说明:key不重复,value可以重复
put() 添加/更新元素
get() 获取元素,key不存在返回null
getOrDefault() 获取元素,key不存在返回默认
remove() 删除元素
containsKey()/containsValue() 检查map中是否包含某个key或value
keySet() and values() 获取所有的键或值
size() 返回当前map的大小
clear() 删除所有元素
isEmpty() 检查是否为空
putAll() 把两个map合并为一个
迭代hashMap:
Map.Entry类表示字典中的键值对。entrySet()方法返回HashMap中所有对的列表。
HashMap的Oracle官方文档: