Java容器
容器
1.Iterable 接口和 Iterator 接口
Iterable接口从 JDK 1.5 开始出现,是 Java 容器的最顶级的接口之一,该接口的作用是使容器具备迭代元素的功能。
Iterator接口从 JDK 1.2 开始出现,其含义是迭代器,可以用于迭代容器中的元素。
Iterable 接口的方法
iterator
方法 iterator 是 Iterable 接口的核心方法,返回 Iterator 类的迭代器实例。
forEach
方法 forEach 从 JDK 1.8 开始出现。该方法有默认实现,其作用是对容器中的每个元素进行处理。
spliterator
方法 spliterator 从 JDK 1.8 开始出现。该方法有默认实现,其作用是并行遍历元素。
Iterator 接口的方法
hasNext
方法 hasNext 的作用是检测容器中是否还有需要迭代的元素。
next
方法 next 的作用是返回迭代器指向的元素,并且更新迭代器的状态,将迭代器指向的元素后移一位。
remove
方法 remove 的作用是将迭代器指向的元素删除。
该方法有默认实现,默认实现为抛出 UnsupportedOperationException 异常,如果迭代器迭代的容器不支持 remove 操作,则对迭代器调用方法 remove 时会抛出 UnsupportedOperationException 异常。
forEachRemaining
方法 forEachRemaining 从 JDK 1.8 开始出现。
该方法有默认实现,其作用是对容器中的剩余元素进行处理,直到剩余元素处理完毕或者抛出异常。
2.Collection 接口
Collection接口统一定义了单列容器,该接口继承了Iterable接口。
Collection 接口的常用方法
添加元素
添加元素的方法有 add 和 addAll,其中 add 一次添加一个元素,addAll 一次将另一个容器中的元素全部添加到当前容器中。
方法 addAll 和集合的并集运算相似。
删除元素
删除元素的方法有 remove、removeAll 和 clear
remove一次删除一个元素removeAll一次将另一个容器中的元素全部从当前容器中删除clear删除当前容器中的全部元素
方法 removeAll 和集合的差集运算相似。
保留元素
保留元素的方法有 retainAll。
该方法保留既在当前容器中又在另一个容器中的元素。
和集合的交集运算相似。
判断包含元素
判断包含元素的方法有 contains 和 containsAll
contains判断当前容器是否包含一个指定元素containsAll判断当前容器是否包含另一个容器中的全部元素
其他方法
-
方法
isEmpty判断当前容器是否为空(即不包含元素) -
方法
size返回容器中的元素数目 -
方法
toArray将容器转化成 Object 数组并返回
Collection 接口和其他容器类的关系
List 和 Set 是 Collection 接口的子接口。
List是线性表,存储一组顺序排列的元素。Set是集合,存储一组互不相同的元素。
另一个描述容器的接口是 Map,该接口与 Collection 并列存在。
不同于*** Collection 接口存放单值元素,Map 接口存放的是键值对。***
3.线性表
List 接口定义线性表,该接口继承了 Collection 接口。
List 接口的实现类有 ArrayList、LinkedList 和 Vector。
List 接口的常用方法
由于 List 接口继承了 Collection 接口,因此 List 接口支持 Collection 接口的一切方法。
List 接口还支持通过下标访问元素,根据下标进行添加和删除元素的操作,以及可以生成双向遍历线性表的新迭代器。
以下列举的方法是 List 接口中新定义的方法(和 Collection 相比新定义的方法)。
添加元素
添加元素的方法有 add 和 addAll
add一次添加一个元素addAll一次将另一个容器中的元素全部添加到当前线性表中。
这两个方法都可以指定下标,在指定下标处添加元素。
删除元素
删除元素的方法有 remove
可以指定下标,删除指定下标处的元素。
修改元素
修改元素的方法有 set,将指定下标处的元素修改成新的元素。
获得元素以及获得元素下标
获得元素的方法有 get,返回指定下标处的元素。
获得元素下标的方法有 indexOf 和 lastIndexOf,分别返回第一个匹配元素的下标和最后一个匹配元素的下标。
获得子线性表
获得子线性表的方法有 subList,返回指定下标范围的子线性表。
生成线性表迭代器
生成线性表迭代器的方法有 listIterator
-
该方法如果没有参数则返回线性表中元素的迭代器
-
如果指定下标则返回从指定下标开始的元素的迭代器
线性表迭代器的接口是 ListIterator,该接口继承了 Iterator 接口,支持双向遍历。
向量类 Vector
Vector 类和 ArrayList 类的方法基本是相同的,主要区别是 Vector 类的所有方法都是同步的,因此可以保证线程安全。
虽然 Vector 是线程安全的,但是同步操作会花费更多的时间。
在不需要保证线程安全的情况下,使用 ArrayList 比使用 Vector 效率更高。
思考
ArrayList 和 LinkedList 的主要区别是什么?从底层实现、随机访问元素、插入和删除元素方面回答。
ArrayList的底层实现是数组,LinkedList的底层实现是双向链表。ArrayList可以快速访问指定下标处的元素,LinkedList需要遍历元素才能得到指定下标处的元素。ArrayList插入和删除元素时需要移动其他元素(除了在尾部插入和删除元素的情况),LinkedList可以快速插入和删除元素,但是在指定位置(除了头部和尾部)插入和删除元素时则需要首先遍历元素到指定位置。
ArrayList 和 Vector 的主要区别是什么?什么情况下使用 ArrayList 比使用 Vector 更好?
ArrayList 和 Vector 的主要区别是:
-
Vector的所有方法都是同步的,因此可以保证线程安全, -
ArrayList不能保证线程安全。
在不需要保证线程安全的情况下,使用 ArrayList 比使用 Vector 效率更高,因此使用 ArrayList 更好。
4.映射和集合
Map 接口定义映射,存储一组键值对的映射关系。
Set 接口定义集合,存储一组互不相同的元素,该接口继承了 Collection 接口。
Map 接口的概念和常用方法
Map接口存储一组键值对的映射关系,映射中的每个键对应一个值。映射中不能有重复的键,否则会出现一个键对应多个值的情况,这违背了映射的定义。
放置键值对
放置键值对的方法有 put 和 putAll,
put一次放置一个键值对,putAll一次将另一个映射中的键值对全部添加道当前映射中。
在映射中放置键值对时,如果映射中没有对应的键,则在映射中新建一个键值对,否则用新的键值对覆盖原来的相同键的键值对。
删除键值对
删除键值对的方法有 remove 和 clear
remove删除指定键的键值对clear删除当前映射中的全部键值对
判断包含键或值
判断包含键或值的方法有 containsKey 和 containsValue
containsKey判断映射中是否包含指定的键containsValue判断映射中是否包含指定的值
根据键获得值
根据键获得值得方法有 get,该方法返回映射中指定键的值。
获得键或键值对的集合
获得键或键值对的集合的方法有 entrySet 和 keySet
entrySet返回映射的所有键值对的集合keySet返回映射的所有键的集合
获得值的容器
获得值的容器的方法有 values,该方法返回映射的所有值的容器。
其他方法
-
方法
isEmpty判断当前映射是否为空(即不包含键值对) -
方法
size返回映射中的键值对数目。
Map 接口的实现类 HashMap、Hashtable 和 TreeMap
HashMap 和 Hashtable
HashMap 类是散列映射,通过散列函数计算键对应的存储位置。
因此可以快速地完成放置键值对、删除键值对、根据键获得值的操作。
JDK 1.8 之前的 HashMap 的底层通过数组和链表实现,如果出现冲突则通过拉链法解决冲突。
JDK 1.8 在解决冲突时的实现有较大变化,当链表长度大于阈值(默认为 8)时,将链表转化为红黑树,以减少搜索时间。
Hashtable 类是散列表,其功能和 HashMap 相似。
以下是 HashMap 和 Hashtable 的部分区别。
HashMap不是线程安全的,Hashtable的大多数方法用关键字synchronized修饰,因此Hashtable是线程安全的。- 在不需要保证线程安全的情况下,
HashMap的效率高于Hashtable。 HashMap允许键或值为null,只能有一个键为null,可以有一个或多个键对应的值为null,Hashtable不允许键或值为null。- 从 JDK 1.8 开始,
HashMap在链表长度大于阈值(默认为 8)时,将链表转化为红黑树以减少搜索时间,Hashtable没有这样的机制。
TreeMap
TreeMap 是有序映射,键可以使用 Comparable 接口或 Comparator 接口排序。
TreeMap 的底层实现是红黑树,通过红黑树维护映射的有序性。由于要维护映射的有序性,因此 TreeMap 的各项操作的平均效率低于 HashMap,但是 TreeMap 可以按照顺序获得键值对。
Set 接口的定义和常用方法
Set 接口存储一组互不相同的元素,一个集合中不存在两个相等的元素。
Set 接口继承了 Collection 接口,没有引入新的方法或常量,只是规定其实例不能包含相等的元素。
Set 接口的实现类 HashSet 和 TreeSet
HashSet
HashSet 类是散列集合,其底层实现基于 HashMap。
- 当对象加入散列集合时,需要判断元素是否重复,
- 首先通过方法
hashCode计算对象的散列码检查是否有对象具有相同的散列码, - 如果没有相同的散列码则没有重复元素,否则再通过方法
equals检查是否有相等的对象。
- 首先通过方法
根据散列约定,如果两个对象相同,它们的散列码一定相同。
因此如果在子类中重写了 equals 方法,必须在该子类中重写 hashCode 方法,以保证两个相等的对象对应的散列码是相同的。
TreeSet
TreeSet 类是有序集合,其底层实现基于 TreeMap。
和 TreeMap 相似,TreeSet 可以使用 Comparable 接口或 Comparator 接口对元素排序。
HashSet的底层实现基于HashMap,元素是无序的,通过方法hashCode和equals保证元素没有重复;TreeSet的底层实现基于TreeMap,元素是有序的,通过Comparable接口或Comparator接口保证元素没有重复。
浙公网安备 33010602011771号