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 list)方法,该方法返回一个线程安全的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对象);