一.集合由来
1.当需要在Java程序中记录单个数据内容时,则声明一个变量。
2.当需要在Java程序中记录多个类型相同的数据内容时,声明一个一维数组。
3.当需要在Java程序中记录多个类型不同的数据内容时,则创建一个对象。
4.当需要在Java程序中记录多个类型相同的对象数据时,创建一个对象数组。
5.当需要在Java程序中记录多个类型不同的对象数据时,则准备一个集合。
二.集合框架结构
Java中集合框架顶层框架是:java.util.Collection集合 和 java.util.Map集合。 其中Collection集合中存取元素的基本单位是:单个元素。 其中Map集合中存取元素的基本单位是:单对元素。
三.集合常见接口和实现类
接口 | 特点基本描述 | |||
集 合 | interface Collection | interface List (该集合中允许有重复的元素并且有先后放入次序。) | ArrayList | 随机访问快,插入与删除元素的速度慢 |
LinkedList | 访问慢,插入与删除元素的速度快,可以当作栈、队列、双向队列使用 | |||
Stack | Stack类的底层是采用动态数组进行数据管理的,该类主要用于描述先进后出的特征. | |||
Vector | 采用动态数组进行数据管理的,该类与ArrayList类相比属于线程安全的 类,效率比较低,以后开发中基本不用。 | |||
interface Set (不允许重复。) | HashSet | 利用哈希算法存储,存取速度快 | ||
LikedHashSet | 其中LinkedHashSet类与HashSet类的不同之处在于内部维护了一个双向链表,链表中记录了元素的迭代顺序,也就是元素插入集合中的先后顺序,因此便于迭代。 | |||
TreeSet | 实现了SortedMap接口 | |||
Interface Queue | LinkedList | LinkedList 基于双向链表实现的非线程安全的集合。 | ||
interface Map (该集合中key是不允许重复的,而且一个key只能对应一个value。) | HashMap(无序) | 底层是采用哈希表进行数据管理的,jdk1.8及以后hash冲突大于等于8转换为红黑树。 | ||
TreeMap(有序。注:树中序遍历保证了有序性) | 底层是采用红黑树进行数据管理的 |
[注:(相关的常量:
DEFAULT_INITIAL_CAPACITY : HashMap的默认容量是16。
DEFAULT_LOAD_FACTOR:HashMap的默认加载因子是0.75。
threshold:扩容的临界值,该数值为:容量*填充因子,也就是12。
TREEIFY_THRESHOLD:若Bucket中链表长度大于该默认值则转化为红黑树存储,该数值是8。
MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量,该数值是64。)]
1.List、Set、Map之间区别是什么?
List:元素可重复,有序集合。
Set:LinkedHashSet按照插入排序, SortedSet可排序,HashSet无序,不重复集合。
Map:key无序,唯一;value不要求有序,允许重复。
2.元素放入HashMap的原理?
使用元素的key调用hashCode方法获取对应的哈希码值,再由某种哈希算法计算在数组中的索引位置。若该位置没有元素,则将该键值对直接放入即可。若该位置有元素,则使用key与已有元素依次比较哈希值,若哈希值不相同,则将该元素直接放入。若key与已有元素的哈希值相同,则使用key调用equals方法与已有元素依次比较。若相等则将对应的value修改,否则将键值对直接放入即可。
3.元素放入HashSet的实现原理?
使用元素调用hashCode方法获取对应的哈希码值,再由某种哈希算法计算出该元素在数组中的索引位置。若该位置没有元素,则将该元素直接放入即可。若该位置有元素,则使用新元素与已有元素依次比较哈希值,若哈希值不相同,则将该元素直接放入。若新元素与已有元素的哈希值相同,则使用新元素调用equals方法与已有元素依次比较。若相等则添加元素失败,否则将元素直接放入即可。
思考:为什么要求重写equals方法后要重写hashCode方法呢?
解析:
当两个元素调用equals方法相等时证明这两个元素相同,重写hashCode方法后保证这两个元素得到的哈希码值相同,由同一个哈希算法生成的索引位置相同,此时只需要与该索引位置已有元素比较即可,从而提高效率并避免重复元素的出现。
4.TreeSet的原理是什么?
TeeSet基于TreeMap实现,TreeMap基于红黑树实现。
5.ArrayList和Vector的联系和区别
相同点:底层都使用数组实现;功能相同,实现增删改查等操作的方法相似;长度可变的数组结构。
不同点:Vector是早期JDK版本提供,ArrayList是新版本替代Vector的;Vector的方法都是同步的,线程安全,ArrayList非线程安全,但性能比Vector好;默认初始化容量都是10,Vector扩容默认会翻倍,可指定扩容的大小,ArrayList只增加50%。
6.HashMap和Hashtable有什么区别?
安全性不同:HashMap线程不安全;Hashtable中的方法是Synchronize的.
key,value是否允许为null:HashMap中value都可以是 null,key只允许一个null;Hashtable中
key,value都不允许为空。
迭代器不同:HashMap的Iterator是fail-fast迭代器;Hashtable还使用了enumerator迭代器.
hash的计算方式不同:HashMap计算了hash值;Hashtable使用了key的hashcode方法。
默认初始大小和扩容方式不同:HashMap默认初始化大小16,容量必须是2的整数次数幂,
扩容时将容量变为原来的2倍;Hashtable默认初始化大小11,扩容时将容量变为原来的2
倍加1;
是否有contains方法:HashMap没有contains方法;Hashtable包含contains方法,类似于
containsValue。
父类不同:HashMap继承自AbstractMap;Hashtable继承自Dictionary。
四.泛型
四.泛型
基本概念:
通常情况下集合中可以存放不同类型的对象,是因为将所有对象都看做Object类型放入的,因此 从集合中取出元素时也是Object类型,为了表达该元素真实的数据类型,则需要强制类型转换, 而强制类型转换可能会引发类型转换异常。 为了避免上述错误的发生,从Java5开始增加泛型机制,也就是在集合名称的右侧使用<数据类型> 的方式来明确要求该集合中可以存放的元素类型,若放入其它类型的元素则编译报错。 泛型只在编译时期有效,在运行时期不区分是什么类型。
原理:
泛型的本质就是参数化类型,也就是让数据类型作为参数传递,其中E相当于形式参数负责占位, 而使用集合时<>中的数据类型相当于实际参数,用于给形式参数E进行初始化,从而使得集合中所 有的E被实际参数替换,由于实际参数可以传递各种各样广泛的数据类型,因此得名为泛型。
五.泛型通配符的使用
有时候我们希望传入的类型在一个指定的范围内,此时就可以使用泛型通配符了。
如:之前传入的类型要求为Integer类型,但是后来业务需要Integer的父类Number类也可以传
入。
泛型中有三种通配符形式:
<?> 无限制通配符:表示我们可以传入任意类型的参数。
<? extends E> 表示类型的上界是E,只能是E或者是E的子类。
<? super E> 表示类型的下界是E,只能是E或者是E的父类。