一、List
1、list集合存储元素特点:
有序---存进去和取出来顺序一样,list集合中元素有下标,从0开始,以1递增
可重复---可以多次存储相同的元素
2、list集合是父接口collection接口的扩展,
既包含父接口共有的方法,又有自己特有的方法
(1)和父接口共有方法
add(对象)-----添加某个元素,默认在集合末尾添加元素
remove(对象)----删除某个元素
contains(对象)----是否包含某元素
clear()-----清空
size()-----获取集合中元素个素
isEmpty()-----是否为空
(2)list特有方法----下标
add(下标,元素)----在指定位置添加元素(方法使用较少,对于arrayList效率较低)
set(下标,元素)----修改指定位置元素的值
get(下标)-----------根据下标获取元素
remove(下标)-------删除
indexOf(对象)------获取指定对象第一次出现处的下标
lastIndexOf(对象)------获取指定对象最后一次出现处的下标
(3)list特有遍历方式
List<String> mylist=new ArrayList<>();
for(int i=0;i<mylist.size();i++){
System.out.println(mylist.get(i));// 通过下标get元素
}
(4)迭代器方式遍历
Iterator it=mylist.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
(一)ArrayList
1、底层实现---数组
优点:检索效率比较高
原因每个元素占用空间大小相同,内存地址是连续的,知道首元素内存地址,知道下标就可以通过数学表达式计算出元素的内存地址
缺点:随机增删效率比较低,但数组集合元素的添加一般向数组末尾添加元素,效率很高,不受影响
数组不能存储大数据量
2、ArrayList----用得最多的集合,检索效率快,添加效率快,末尾添加元素不影响效率,我们检索/查找某个元素的操作比较多
3、ArrayList默认初始化容量是10
4、数组扩容---1.5倍
(1)当元素添加的个数大于默认或指定集合容量,系统会对集合进行扩容
(2)扩为原容量的1.5倍
容量二进制右移1位--->>1,即扩展原容量一半的容量
10----00001010 >>1 00000101------5 和----15
- k=1.5时,就能充分利用前面已经释放的空间。
如果k >= 2,新容量刚刚好永远大于过去所有废弃的数组容量。
- 可以充分利用移位>>操作,减少浮点数或者运算时间和运算次数。
new=old+(old>>1)=old+(old/2)
【注】要尽可能少的扩容
因为数组扩容效率较低,建议在使用ArrayList集合时,预估元素个数,给定一个初始化容量
5、ArrayList是非线程安全的
(二)LinkedList
1、底层实现---双向链表
(1)最基本的单元是节点,节点有两个属性:数据+下一个节点的内存地址(next)
(2)头节点----始终指向头元素
尾节点,next=null----始终指向尾元素
2、优缺点:
优点:随机增删元素效率较高,增删元素不涉及到大量元素的位移-----业务中随机增删业务时,建议使用
缺点:查询效率较低,每次查找某个元素都要从头节点开始查找
3、LinkedList链表没有初始化容量
(三)vector
1、底层是数组,初始化容量是10
2、数组扩容:扩容到原来的2倍
3、vector中所有方法都是线程同步的,都带有synchronized关键字
是线程安全的,效率较低,使用较少
【注】ArrayList与LinkList比较
1、 ArrayList:将检索发挥到极致
LinkedList:将随机增删发挥到极致
2、ArrayList之所以检索效率较高,不单纯是因为下标原因,是因为底层数组发挥的作用,LinkedList也有下标,但检索效率较低,因为只能从头节点开始一个一个遍历
3、 加元素都是往末尾添加,所以ArrayList用较多
二、Set
1、set集合特点:
无序:存入的顺序和取出来顺序不一样,且没有下标
不可重复:存的值不可重复,若重复,只存储一个
2、set集合的遍历:
HashSet<String> set=new HashSet<>();
//泛型是什么类型,遍历时定义什么类型的形参
for(String s:set){
System.out.println(s);
}
(一)HashSet
1、底层HashMap(哈希表)
2、HashMap的key部分是一个Set集合(无序不可重复)
(二)TreeSet(SortedSet接口的实现类)
1、底层结构:
(1)TreeSet集合底层实际是一个TreeMap
(2)TreeMap集合底层是一个二叉树
平衡二叉树,遵循左大右小规则存放(在存的时候按定义规则比较存放)
遍历输出时,次啊用中序遍历方式:左根右
【注】什么序遍历主要依据根的遍历顺序,中序遍历---根在中间
(3)放到TreeSet集合中的元素,等同于放到TreeMap集合的key部分了(TreeMap集合的key部分其实是一个set集合)
2、TreeSet元素特点:
无序不可重复,但可以按照元素大小自动排序
3、自动排序
放入TreeSet的自定义对象(person,student等),需要重写比较规则
系统默认写好,自动排序的对象类型:String Interger Date
4、自定义类型排序实现----比较规则的重写
(1)实现cmparable接口-----重写compareTo方法
class Student implements Comparable<Student>{
类本身属性;
类本身方法;
public int compareTo(Student s){
按需求具体实现比较内容
}
}
这样实现类之后,TreeSet放入Student对象就可以自动排序了。
(2)实现comparator比较器---单独编写比较器类+通过构造方法将比较器传入TreeSet
- 定义比较器:
//类1---Student类
class Student{
属性;
方法
}
//类2----Student比较器类
class StudentComparator implements Comparator<Student>{ //利用泛型固定比较的对象是student
//实现compare方法
public int compare(Student s1,Student s1){
//指定两个对象的比较规则
}
}
- 传入比较器
TreeSet<Student> st=new TreeSet<>(new StudentComparator());//传入student对象比较器
st.add(new Student(1,"zhangsan"));
st.add(new Student(2,"lisi"));
被添加的student对象就会按照比较器定义的比较规则进行自动排序,输出时,按序输出
附:老杜总结图