-
集合也是一个对象,集合中不存储基本数据类型,只存储java中对象的内存地址,(基本类型数据存入集合,java后台会进行自动装箱)
-
java中每种不同的集合都对应一个不同的数据结构,不同的数据结构,存储数据的方式不同。数据结构类型有:顺序表,栈,堆,队列,树,哈希表,链表等。。。例如:java中ArrayList类,Vector类底层为数组,linkedList 底层是链表(双向),TreeMap 底层是二叉树,HashMap类底层是哈希表
-
所有的集合类和集合接口都在java.util.*包下
-
java中集合分为两大类:
一类是单个方式存储元素,其超级父接口是java.util.Collection;
一类是以键值对的方式存储元素,其超级父接口是java.util.Map; -
Java中常用集合的继承结构图
- 总结
ArrayList:底层是数组
linkedList:底层是双向链表
Vector:底层是数组,线程安全的,效率低,使用少
HashSet底层是HashMap,放到HashSet集合中的元素等同于放到了 HashSet集合的key部分
TreeSet:底层是TreeMap,放到TreeSet集合中的元素等同于放到 TreeMap集合中的key部分,底层根据值的大小自动排序
HashMap:底层是哈希表
Hashtable:底层也是哈希表,只不过是线程安全的,效率低,使用较少
TreeMap底层是二叉树
List集合存储元素的特点:
有序可重复
有序:存进去的顺序和取出来的顺序相同,每一个元素都有下标。
可重复:存进去1,可以再存储一个1
Set/Map(Map中的key)集合存储元素的特点:
无序不可重复
无序:存进去的顺序和取出来的顺序不一定相同。另外Set集合中元素没有下标。
不可重复:存进去1,不能再存储1了。
SortedSet/SortedMap(SortedMap中的key)集合存储元素特点:
首先是无序不可重复的,但是SortedSet集合中的元素是可排序的。
无序:存进去的顺序和取出来的顺序不一定相同。另外Set集合中元素没有下标。
不可重复:存进去1,不能再存储1了。
可排序:可以按照大小顺序排列
Map集合中的key就是一个Set集合。往Set集合中放数据,实际上是放到了Map集合中的key部分。注意:Map集合中的key不可重复但是value可以重复!!!
不使用“泛型”能存储Object的所有子类型
使用了“泛型”后,只能存储某个具体元素
注意:集合中不能直接存储基本数据类型和java对象,只存储java中对象的内存地址
| boolean add(E e) | 向集合中添加指定的元素 |
|---|---|
| boolean addAll(Collection extends E> c) | 将指定集合中的所有元素添加到这个集合(可选操作)。 |
| void clear() | 从这个集合中移除所有的元素(可选操作)。 |
| boolean contains(Object o) | 根据equals()方法比较返回 true如果集合包含指定元素。 |
| boolean containsAll(Collection> c) | 返回 true如果这个集合包含指定集合的所有元素。 |
| boolean isEmpty() | 返回 true如果集合不包含任何元素。 |
| Iterator iterator() | 返回此集合中的元素的迭代器。 |
| boolean remove(Object o) | 根据equals()方法比较,从这个集合中移除指定元素的一个实例,如果它是存在的(可选操作)。 |
| boolean removeAll(Collection> c) | 删除此集合中包含的所有元素(可选操作)的所有元素(可选操作)。 |
| boolean retainAll(Collection> c) | 仅保留包含在指定集合中的这个集合中的元素(可选操作)。 |
| int size() | 返回此集合中的元素的数目。 |
| Object[] toArray() | 返回包含此集合中所有元素的数组。 |
1.通过Collection接口中的iterator()方法获得迭代器对象
2.迭代器对象初始位置指向集合数据的前一个位置
3.迭代器的通用方法
- next()移动迭代器对象使其指向集合的下一个元素并以Object对象返回该元素的值
- hasNext(),判断是否还有下一个元素
- remove(),底层调用equals方法进行比较,存在该对象则删除集合中的该元素
注意:集合结构只要发生变化,迭代器就必须重新获取,否则会出现异常 在使用迭代器进行迭代时,应该使用迭代器中的remove()方法这样就能使得集合中的结构和迭代器指向的结构对应,而不是集合对象的remove()方法,因为集合对象在调用remove()方法时会改变集合中的结构,此时迭代器对象需要重新获取,否则会发生异常
Collection中的contains(Object o)判断集合中是否包含集合该对象,底层调用equals方法比较,(存储的类型未重写equals()方法,则默认比较内存地址)(注意:如果是String类,则比较内容,因为String类的equals()方法被重写,比较的是内容),相同返回ture
三、List接口 1.List集合的特点1.List接口继承Collection接口
2.List集合中的元素有序可重复,即元素有下标,存取顺序一致,可以存储相同的元素
3.集合元素下标从0开始
Collection接口中的方法都可以用
| boolean add(int index ,Object element ) | 向指定位置插入新元素 |
|---|---|
| booleanadd(Object element ) | 向集合末尾中添加新元素 |
| int get(int index) | 得到集合中指定位置的元素 |
| int indexOf(Object element) | 获取指定对象第一次出现的索引 |
| int LastIndexOf(Object element) | 获取指定对象最后一次出现的索引 |
| void remove(int index ) | 删除指定位置的元素 |
| set(int index ,Object element) | 修改指定位置的元素 |
1.ArrayList类的无参构造方法默认容量为10(最初为0,当添加一个元素后初始化容量为10),
2.ArrayList(int initialCapacity) 构造一个长度为initialCapacity的集合
3.ArrayList(Collection c)通过实现了Collection接口的对象创建数组
3.如果add()添加的元素超过初始化容量,则底层自动将容量扩充为原来的1.5倍,扩容效率较低,优化策略,因为底层为数组,所以使用时建议预估计容量创建,
补充:数组扩容方法Arrays.copyOf(array,2*array.length);//第一个参数是待拷贝的数组对象,第二个是新数组的长度
4.底层是Object类数据
5.ArrayList 优点检索效率高
缺点,随机增删效率低(但向末尾添加元素效率高,不受影响
),无法存储大量数据,因为数组很难找到一大片连续的内存空间
linkList集合底层为双向链表:
优点:随机增删效率高,不涉及大量元素的位移操作
缺点:查找的效率较低,每次查找元素都需要从表头开始遍历
特点:初始化没有任何元素,空间存储上内存地址不连续,适合存储数据量大的数据
特点:线程同步安全的,效率较低,底层为数组,无参构造初始化为10个元素,溢出扩容两倍
补充说明:将非线程安全的ArrayList变成线程安全的
(Collections工具类的静态方法sychronizedList(Collection obj)方法将集合obj变成线程安全的)
Set集合特点:
Set集合是无序不可重复的,放在Set集合中的元素相当于放在了Map集合中的key部分
JDK5.0之后推出的特性
语法:for(类型(和被遍历的集合或数组存储的元素类型一致) 变量名:数组或者集合){
}
优点,遍历方便
缺点,没有下标,不能删除集合元素
1、对于数组,foreach 循环实际上还是用的普通的 for 循环
2、对于集合,foreach 循环实际上是用的 iterator 迭代器迭代
注意:Map和Collection没有关系
1.Map集合中的常用方法| V put(K key ,V value ) | 向Map集合中添加键值对 |
|---|---|
| V get(Object key) | 通过key获取value |
| void clear() | 清空Map集合 |
| boolean containsKey(Object key) | 判断Map集合中是否含有某个key |
| boolean containsValue(Object value) | 判断Map集合中是否含有某个value |
| boolean isEmpty() | 判断Map集合中的元素是否全为空 |
| Set(K) keySet() | 获取Map集合中所有的key |
| V remove(Object key) | 移除Map集合中key元素的键值对 |
| default V replace(K key) | 根据给定的key移除对应的元素 |
| int size() | 返回键值对的数目 |
| Collection values() | 返回Map集合中所有的value |
| Set | 将Map集合转为Set集合 |
ps:containsX()这两个方法底层都是调用equals()方法进行比较,自定义类比较值需要重写,Entry是Map的静态内部类,
2.Map集合中的遍历1.通过keySet()方法获取所有的key,然后遍历
(注意HashMap的key可以为空,且只有一个,value也可以为空)
2.通过 entrySet()方法转换成存储Map.Entry(本质上是Node节点组成的单链表)元素的Set集合,效率较高,通常使用该方法对Map集合进行遍历
Map集合遍历总结:
1、通过key集合访问,对Key敢兴趣,可以访问与key对应的Value值;
for(String k:maps.keySet()){
System.out.println(k+":"+maps.get(k));
}
2、通过value集合访问,只对value值感兴趣,无法访问key值;
for(String value:maps.values()){
System.out.println(value);
}
3、通过Entry集合访问,对Entry感兴趣,可以访问与key对应的Value值
for(Entry entry:maps.entrySet()){
System.out.println(entry.getKey()+":"+entry.getValue());
}
4、通过迭代Key集合访问Map集合,maps.keySet()返回的是一个Set集合,Set直接继承Collection,所以可以对其进行迭代。
Iterator iterator = maps.keySet().iterator();
while(iterator.hasNext()){
String key = iterator.next();
System.out.println(key+":"+maps.get(key));
}
5、通过迭代Values集合访问Map集合,maps.values()返回的是Collection,所以可以对其迭代。
Iterator iter= maps.values().iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
6、通过迭代Entry集合访问Map集合,maps.entrySet()返回的是一个Set>,Set直接继承Collection,所以可以对其迭代。
Iterator> it = maps.entrySet().iterator();
while(it.hasNext()){
Entry entry = it.next();
System.out.println(entry.getKey()+":"+entry.getValue());
}
3.散列表/哈希表
哈希表是一个数组和单链表的结合体
数组:查询效率高,增删效率低
单向链表:随机增删效率高,查询方面效率低
哈希表将者两种数据结构组合在一起,充分发挥他们各自的优点(数组用于存储链表的表头节点,然后往对应的表头上加元素)
第一步:将k v 键值对封装到Node对象中,
第二步:底层会调用hashCode()方法得到k对应的hash值,然后通过哈希算法,将hash值转换为对应数组的下标,下标位置上如果没有任何元素,就把Node添加到这个位置上,如果对应的位置上有链表,此时会拿着k和链表上的每一个节点中的k进行equals()方法比较,如果都返回false则将该node添加到链表的末尾/或表头,如果有一个equals方法返回true则这个节点将会被覆盖。
先调用k的hashCode()方法得出哈希值,通过哈希算法转换成数组的下标,通过数组下标快速定位到某个位置上,如果这个下标上面什么都没有,返回null,如果这个下标位置上有(单)链表,则k会与每个单链表上的key值进行equals()比较,如果所有的equals方法都返回false则get方法会返回null,只要有一个equals方法返回true,则此时这个节点的value就是我们要的value,则get方法就会返回这个value
6.HashMap类1.放在HashMap集合中的key元素部分和放在HashSet元素部分需要同时重写hashCode()和equals()方法
2.HashMap集合初始化的数组容量是16,默认加载因子是0.75,即存储的数据达到数组容量的75%时会自动扩容为原来的2倍
注意:1.HashMap的初始化容量必须是2的倍数,这是官方推荐,目的是为了哈希表散列分布均匀,提高HashMap的存取效率。2.如果hashCode()方法和equals()方法使用IDEA生产时,需要同时生成
3.JDK8之后对HashMap集合的改进,加了门限值8,即:如果单向链表上的元素个数为8时,会自动把单向链表变成二叉树/红黑树,当元素个数又减小到6时,又会把树变成单向链表
Hashtable的初始化容量为11,默认加载因子也为0.75,扩容方式为原容量的二倍再加1,注意:但是Hashtable的key和value 都不能为空,Hashtable集合是线程安全的
8.properties类他是Hashtable的子类,它是属性类,它的key和value都是String类,是线程安全的,主要掌握put()和get()方法
9.TreeMap/TreeSet类特点是无序不可重复,但里面的元素自动排序(数据结构为搜索二叉树),排序需要实现Comparable接口重写compareTo()或传递Comparator接口的比较器对象为集合的排序提供一个比较的依据,对于String和Integer等类型已经实现了Comparable接口的比较功能,我们只有要对我们存储在该集合中的自定义类型实现该接口,并重写compareTo()方法,可以不重写equals()方法。
10、集合比较规则的重写:1.Comparable接口的compareTo()方法比较规则的重写方式
降序:k1.compareTo(k2),k1比k2大返回大于0的数,k1等于k2返回0,k1比k2小返回小于0的数,即:将列表中的元素作为参数和待加入的元素比较,返回小于0的数则放在二叉树的左边,大于0则放在二叉树右边,等于零则覆盖
2.Comparator接口,该接口需要实现compare()方法,它的两个参数分别是待插入节点和集合中的元素
3.TreeSet/TreeMap也可以****通过构造器传递该比较器实现类对象实现比较规则,通常用于比较规则进场发生改变的类,原理和compareTo()方法类似,在TreeSet集合底层,如果传递了Comparator比较器类对象,则优先使用Comparator比较器的比较规则
常用方法:
| static void copy(List super T> dest, List extends T> src) | 将所有的元素从一个列表复制到另一个列表中。 |
| static | 指定列表为升序排序(集合中的元素排序需要实现Comparable接口) |
| static void sort(List list, Comparator super T> c) | 根据指定的比较器指定的顺序对指定的列表进行排序。 |
| static List synchronizedList(List list) | 返回由指定列表支持的同步(线程安全)列表。 |
创作不易,对您有所帮助的话可以点个赞支持下哦!!!



