java基础笔记09 - 集合
九 Java集合
讲道理,这一章,以后分类型学习一下吧,现在就大致看看好了
集合分为Collection和Map两大体系
Collection接口
List接口:元素有序,可重复
ArrayList,LinkedList,Vector主要实现类
Set接口:元素无序,不可重复
HashSet,LinkedHashSet,TreeSet
Map接口: key-value
HashMap,LinkedHashMap,TreeMap,Hashtable,Properties实现类
1. Collection
讲真,不如看文档。。。
1.1 接口中的方法
Collection coll=new ArrayList();
Collection coll1=Arrays.asList(1,2,3);
coll.add(123);
coll.add(new Person("jerry"));//像Collectioin接口实现类的对象中添加obj时,需要obj类重写equals方法
coll.add(new String("sdf"));
coll.add(false);
coll.remove(123);
coll.addAll(coll1);//添加集合coll1里面的所有元素
coll.removeAll(coll1);//删除的是交集
coll.retaiAll(coll1);//干啥用的?查文档去
coll.equals(coll1);//内容是否相等 ,重写了
coll.toArray();
coll.iterator();//返回遍历的迭代器接口
2. Map
Map接口实现关系:
|------HashMap 最主要的实现类,线程不安全,key和value都可以是null
|------LinkedHashMap: 在HashMap基础上,添加了双向指针,指向add的前后关系
|-----Hashtable :过于古老,key和value不能是null
|------Properties 常用于处理配置文件 key和value都是String 类型,
|------TreeMap:按照key的某种顺序来排序,实现排序遍历
新结构:CurrentHashMap
2.1底层:
key:无序,不可重复,使用Set存储,Key所在的类要重写equals()方法和hashcode()方法
value:无序,可重复,使用Collection存储
key-value对 称为一个Entry:无序,不可重复,使用Set存储
2.2 底层实现原理
2.2.1 JDK7中
HashMap map=new HashMap();
//实例化后,底层创建了一个长度为16的一维数组 Entry[] table
map.put(keyn,valuen);
//其中的某一次put:
//首先调用Key1所在类的hashCode()方法计算hash值,通过哈希函数,得到Entry数组中的存放位置
//如果此位置数据为空,则keyn-valuen添加成功
//如果不为空,则比较此位置上存在的一个或多个数据(链表),的hash值,
//如果哈希值都不同,则添加在此位置上
//如果相同了,再比较keyn所在类的equals方法,
//一样则添加失败(key已存在),但是要更新values
//不一样则继续比较该位置其他数据
//在添加过程中会涉及到扩容,默认扩容2倍,并将原有数据复制过来,再丢弃旧的
2.2.2 JDK8中
new HashMap();//底层不创建数组,并且不叫Entry了,改名Node[] table了
m.put(key1,value1);
//首次调用put方法时,底层创建长度16的Node[] table
//jdk7中的底层:数组+链表
//jdk8中的底层:数组+链表+红黑树
//当数组的某一个索引位置上的元素链表长度>8 且 当前数组长度>64时,此索引位置上的链表改为红黑树存储
//扩容的时候,涉及到临界因子,默认0.75,比如:16*0.75=12,当数组填充到12个之后,就开始扩容了
2.3 LinkedHashMap
2.4 TreMap
添加元素:要求Key必须是同一个类创建对象
2.5 Properties
//需要抛出异常,或者try
Properties pros = new Properties();
FileInputStream fis = new FileInputStream(jdbc.properties);
pros.load(fis);
String name = pros.getProperty("name");
String pws= pros.getProperty("password");
3. Iterator迭代器接口
3.1 迭代器模式
提供一个方法,访问容器对象的每个元素,又不暴露对象得内部细节
iterator()方法的每次调用,都会返回一个新的迭代器!!!
Iterator iter= coll.iterator();//默认游标在第一个元素之前
iter.hasNext();//判断是否还有元素了
iter.next();//返回迭代中的下一个元素。
tier.remove();//不同于集合里面的remove方法,但是效果差不多。。
//注意每次调用迭代器的remove方法之前,必须先调用next方法,也不能多次连续remove,会报错的
3.2 foreach
底层就是个迭代器
for(object obj:coll){
}
for(double d:Array){
}
4. Collection 子接口 :List
通常使用List代替数组
List:元素有序,可重复,有索引,自动扩容
List接口得实现类:ArrayList,LinkedList,Vector
4.1 ArrayList
线程不安全,效率很高,所以用的很多
万一哪天用到了ArrayList恰好又是个临界资源咋办,Collections工具类中提供了一个synchronizedListI(List
别问,就是不用Vetor
JDK7中
底层就是个 Object[] elementDate 存储 ,注意这个是个定长数组,扩容是java自动完成的,默认扩容1.5倍,每次都是抛弃旧的,创建新的
建议开发中使用带参构造器
ArrayList L= new ArrayList(initialCapacity=50)
JDK8中
声明的时候是不开辟空间的,第一次add方法的时候才创建底层的数组
其他差不多
4.2 LinkedList
和上面的ArryList的区别主要就是底层实现:
使用双向链表存储,底层实现了一个类似于链表的结构体类,记录了链表的开始和结尾位置
对于频繁的插入和删除操作,效率超高
直接看JDK8中的就行
LinkedList L = new LinkedList();
每次add放在最后(底层调用linkLast()方法)
4.3 List接口的方法:
关注一下底层是咋写出来的。
List作为Collection 的子接口,多了一些关于索引的方法
比如add,addAll,remove ,subList,set,get,lastindexOf,indexOf
void add(int index,Object ele);//index位置插入元素ele
boolean addAll(int index,Collection eles);//从index位置开始把eles里面的元素挨个添加进去
Object get(int index);
int indexOf(Object odj);//返回元素首次出现的位置,没有返回-1
int lastIndexOf(Object obj);//返回obj在在集合中末次出现的位置
Object remove(int index);//删除元素
Object remove(Obejct obj);
Object set(int index,Obejct ele);//设置指定位置的元素为ele
List subList(int fromIndex,int toIndex);//返回子集合左开右闭
int size();
注意如果遇到了一个int类型的list或者list里面有int类型
则remove(2)默认删除的是index=2
如果想删除元素,需要手动装箱,remove(new Integer(2));
遍历:
//1
Iterator iter=list.iterator();
while(iter.hasNext()){
sout(iter.next());
}
//2
for(Object: list){
sout(obj);
}
//3
for(int i=0;i<list.size();i++){
sout(list.get(i));
}
5. Collection 子接口: Set
set接口没有额外的方法
Set集合不允许重复元素,判断量对象是否相同要用equals()方法,
常见实现类:HashSet,LinkedHashSet,TreeSet
5.1 HashSet
最常见的实现类,基本都用这个
无序,不可重复
我要是new了两个相同的对象,Set也认为时不重复的,因为他俩的hash不同(虽然也是用对象类中的equals方法判断的,)
线程不安全,可以存储null值
HashSet底层是个啥呢。。。是个HashMap。。。没错构造方法里面new HashMap,然后value=null,哪个xx想出来的
底层长啥样呢,数据结构里面的hash链表,一个hash表,每次碰撞冲突之后直接把元素链接在表冲突位置的下面(JDK8以后,J7中是插入hash表中,然后以前的元素链接在后面)
5.1.1 无序,重复的解释
以HashSet为例:
1.无序
无序 != 随机,至少每次遍历可都是一样的
在添加的时候是根据数据具体的hash值计算hash命中的
2. 重复
比如一个HashSet,add了俩对象,这俩对象都是new出来的,属性还一样,Set认为这是俩元素,因为hash值不一样
但是:也不能通过hash值来做重复判断,因为计算hash后可能命中相同位置
如果重写equals()和hashcode方法,则这俩对象就是一个了,只add成功了一次
3. add的过程
添加时判断重复,不是挨个比较的,而是通过hashcode()方法计算hash值,然后碰撞检测,每次检测到碰撞之后,再通过equals方法来判断属性是否相同
直到遇到了空白位置可以插入,或者碰撞并属性相同返回add失败
5.2 LinkedHashSet
作为LinkedHashSet的子类
使得遍历时可以按照添加的顺序来(依然是无序的!!!)
底层啥样呢,在HashSet的基础上,每个元素多了一对双向指针,用于指出添加添加元素的位置
5.3 TreeSets
使用红黑树(二叉树的一种?)来存储
可以按照添加对象的指定属性进行排序
so,要求元素类型一致
自定义对象类:要求
a.自然排序,继承Comparable接口,重写compare方法,通过compate方法来比较俩元素是否相同(就不再使用equals了)
b.定制排序,实现Comparator接口重写compare方法,然后TreeSet ts = new TreeSet(comparator对象);
本文来自博客园,作者:荧惑微光,转载请注明原文链接:https://www.cnblogs.com/yinghuoweiguang/p/15732847.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具