-
集合也是一个对象,集合中不存储基本数据类型,只存储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中对象的内存地址
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接口中的方法都可以用
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集合中的常用方法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()返回的是一个Set3.散列表/哈希表集合,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()); }
哈希表是一个数组和单链表的结合体
数组:查询效率高,增删效率低
单向链表:随机增删效率高,查询方面效率低
哈希表将者两种数据结构组合在一起,充分发挥他们各自的优点(数组用于存储链表的表头节点,然后往对应的表头上加元素)
第一步:将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比较器的比较规则
常用方法:
创作不易,对您有所帮助的话可以点个赞支持下哦!!!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)