Java 集合框架有哪些?
Java 集合框架,可以看看 《Java 集合框架》 文章。
?? 说出一些集合框架的优点?
集合框架的部分优点如下:
- 1、使用核心集合类降低开发成本,而非实现我们自己的集合类。
- 2、随着使用经过严格测试的集合框架类,代码质量会得到提高。
- 3、通过使用 JDK 附带的集合类,可以降低代码维护成本。
- 4、复用性和可操作性。
?? 集合框架中的泛型有什么优点?
Java5 引入了泛型,所有的集合接口和实现都大量地使用它。泛型允许我们为集合提供一个可以容纳的对象类型。因此,如果你添加其它类型的任何元素,它会在编译时报错。这避免了在运行时出现 ClassCastException,因为你将会在编译时得到报错信息。
泛型也使得代码整洁,我们不需要使用显式转换和 instanceOf
操作符。它也给运行时带来好处,因为不会产生类型检查的字节码指令。
Java 集合框架的基础接口有哪些?
- Collection ,为集合层级的根接口。一个集合代表一组对象,这些对象即为它的元素。Java 平台不提供这个接口任何直接的实现。
- Set ,是一个不能包含重复元素的集合。这个接口对数学集合抽象进行建模,被用来代表集合,就如一副牌。
- List ,是一个有序集合,可以包含重复元素。你可以通过它的索引来访问任何元素。List 更像长度动态变换的数组。
- Map ,是一个将 key 映射到 value 的对象。一个 Map 不能包含重复的 key,每个 key 最多只能映射一个 value 。
- 一些其它的接口有 Queue、Dequeue、SortedSet、SortedMap 和 ListIterator 。
?? 为何 Collection 不从 Cloneable 和 Serializable 接口继承?
Collection 接口指定一组对象,对象即为它的元素。
- 如何维护这些元素由 Collection 的具体实现决定。例如,一些如 List 的 Collection 实现允许重复的元素,而其它的如 Set 就不允许。
- 很多 Collection 实现有一个公有的 clone 方法。然而,把它放到集合的所有实现中也是没有意义的。这是因为 Collection 是一个抽象表现,重要的是实现。
当与具体实现打交道的时候,克隆或序列化的语义和含义才发挥作用。所以,具体实现应该决定如何对它进行克隆或序列化,或它是否可以被克隆或序列化。在所有的实现中授权克隆和序列化,最终导致更少的灵活性和更多的限制,特定的实现应该决定它是否可以被克隆和序列化。
?? 为何 Map 接口不继承 Collection 接口?
尽管 Map 接口和它的实现也是集合框架的一部分,但 Map 不是集合,集合也不是 Map。因此,Map 继承 Collection 毫无意义,反之亦然。
如果 Map 继承 Collection 接口,那么元素去哪儿?Map 包含 key-value 对,它提供抽取 key 或 value 列表集合( Collection )的方法,但是它不适合“一组对象”规范。
?? Collection 和 Collections 的区别?
- Collection ,是集合类的上级接口,继承与他的接口主要有 Set 和List 。
- Collections ,是针对集合类的一个工具类,它提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
?? 集合框架里实现的通用算法有哪些?
Java 集合框架提供常用的算法实现,比如排序和搜索。
Collections类包含这些方法实现。大部分算法是操作 List 的,但一部分对所有类型的集合都是可用的。部分算法有排序、搜索、混编、最大最小值。
?? 集合框架底层数据结构总结
1)List
- ArrayList :Object 数组。
- Vector :Object 数组。
- LinkedList :双向链表(JDK6 之前为循环链表,JDK7 取消了循环)。
2)Map
- HashMap :
- JDK8 之前,HashMap 由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突)。
- JDK8 以后,在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8 )时,将链表转化为红黑树,以减少搜索时间。
- LinkedHashMap :LinkedHashMap 继承自 HashMap,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成。另外,LinkedHashMap 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑。详细可以查看:《LinkedHashMap 源码详细分析(JDK1.8)》 。
- Hashtable :数组+链表组成的,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的。
- TreeMap :红黑树(自平衡的排序二叉树)。
3)Set
- HashSet :无序,唯一,基于 HashMap 实现的,底层采用 HashMap 来保存元素。
- LinkedHashSet :LinkedHashSet 继承自 HashSet,并且其内部是通过 LinkedHashMap 来实现的。有点类似于我们之前说的LinkedHashMap 其内部是基于 HashMap 实现一样,不过还是有一点点区别的。
- TreeSet :有序,唯一,红黑树(自平衡的排序二叉树)。
什么是迭代器(Iterator)?
Iterator 接口,提供了很多对集合元素进行迭代的方法。每一个集合类都包含了可以返回迭代器实例的迭代方法。迭代器可以在迭代的过程中删除底层集合的元素,但是不可以直接调用集合的 #remove(Object Obj)
方法删除,可以通过迭代器的 #remove()
方法删除。
?? Iterator 和 ListIterator 的区别是什么?
- Iterator 可用来遍历 Set 和 List 集合,但是 ListIterator 只能用来遍历 List。
- Iterator 对集合只能是前向遍历,ListIterator 既可以前向也可以后向。
- ListIterator 实现了 Iterator 接口,并包含其他的功能。比如:增加元素,替换元素,获取前一个和后一个元素的索引等等。
?? 快速失败(fail-fast)和安全失败(fail-safe)的区别是什么?
差别在于 ConcurrentModification 异常:
- 快速失败:当你在迭代一个集合的时候,如果有另一个线程正在修改你正在访问的那个集合时,就会抛出一个 ConcurrentModification 异常。 在
java.util
包下的都是快速失败。
- 安全失败:你在迭代的时候会去底层集合做一个拷贝,所以你在修改上层集合的时候是不会受影响的,不会抛出 ConcurrentModification 异常。在
java.util.concurrent
包下的全是安全失败的。
?? 如何删除 List 中的某个元素?
有两种方式,分别如下:
- 方式一,使用 Iterator ,顺序向下,如果找到元素,则使用 remove 方法进行移除。
- 方式二,倒序遍历 List ,如果找到元素,则使用 remove 方法进行移除。
?? Enumeration 和 Iterator 接口有什么不同?
- Enumeration 跟 Iterator 相比较快两倍,而且占用更少的内存。
- 但是,Iterator 相对于 Enumeration 更安全,因为其他线程不能修改当前迭代器遍历的集合对象。同时,Iterators 允许调用者从底层集合中移除元素,这些 Enumerations 都没法完成。
对于很多胖友,可能并未使用过 Enumeration 类,所以可以看看 《Java Enumeration 接口》 文章。
?? 为何 Iterator 接口没有具体的实现?
Iterator 接口,定义了遍历集合的方法,但它的实现则是集合实现类的责任。每个能够返回用于遍历的 Iterator 的集合类都有它自己的 Iterator 实现内部类。
这就允许集合类去选择迭代器是 fail-fast 还是 fail-safe 的。比如,ArrayList 迭代器是 fail-fast 的,而 CopyOnWriteArrayList 迭代器是 fail-safe 的。
Comparable 和 Comparator 的区别?
- Comparable 接口,在
java.lang
包下,用于当前对象和其它对象的比较,所以它有一个 #compareTo(Object obj)
方法用来排序,该方法只有一个参数。
- Comparator 接口,在
java.util
包下,用于传入的两个对象的比较,所以它有一个 #compare(Object obj1, Object obj2)
方法用来排序,该方法有两个参数。
详细的,可以看看 《Java 自定义比较器》 文章,重点是如何自己实现 Comparable 和 Comparator 的方法。
?? compareTo 方法的返回值表示的意思?
- 大于 0 ,表示对象大于参数对象。
- 小于 0 ,表示对象小于参数对象
- 等于 0 ,表示两者相等。
?? 如何对 Object 的 List 排序?
- 对
Object[]
数组进行排序时,我们可以用 Arrays#sort(...)
方法。
- 对
List<Object>
数组进行排序时,我们可以用 Collections#sort(...)
方法。
有哪些关于 Java 集合框架的最佳实践?
- 基于应用的需求来选择使用正确类型的集合,这对性能来说是非常重要的。例如,如果元素的大小是固定的,并且知道优先级,我们将会使用一个 Array ,而不是 ArrayList 。
- 一些集合类允许我们指定他们的初始容量。因此,如果我们知道存储数据的大概数值,就可以避免重散列或者大小的调整。
- 总是使用泛型来保证类型安全,可靠性和健壮性。同时,使用泛型还可以避免运行时的 ClassCastException 异常。
- 在 Map 中使用 JDK 提供的不可变类作为一个 key,这样可以避免 hashcode 的实现和我们自定义类的 equals 方法。
- 应该依照接口而不是实现来编程。
- 返回零长度的集合或者数组,而不是返回一个
null
,这样可以防止底层集合是空的。
【搞定Java集合类】基础
原文:https://www.cnblogs.com/zwhu1216/p/11386059.html