java基础笔记-集合
九 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
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对象);