数组
-
数据结构:
线性表中的顺序表,在内存中是连续的内存地址,通过数据元素物理存储的连续性来反映数据元素逻辑上的相邻关系。
-
特点
1.定长,可以达到内存最高效的分配
2.可以进行快速随机访问,查询快,增删慢,因为增删的时候会产生物理位置的移动,也就是内存位置的移动
3.可以存放任意类型的元素,但同一数组中存放元素的类型必须相同
-
注意事项
1.数组创建成功后,如果没有赋值的话,会对其中的元素赋予一个默认的值。泛型的类型不同,赋予的默认值不同。
2.如果数组为null的话,访问此数组中的元素会报出空指针异常。
3.如果访问数组的下标超过了数组的length-1,就会报出数组越界异常
4.数组的排序,二分查找,复制,设置元素的值,比较都是通过工具类arrays来完成的
集合
对所有的集合而言,他们都只能存放引用类型的元素,基本类型的元素也必须换成包装类进行存储
在AbstractCollection抽象类中,定义了toArray方法,故所有继承他的list,set集合都可以调用
1.ArrayList
-
数据结构
使用顺序表的结构来实现,内部相当于一个动态可分配的数组。
-
特点
1.能够进行快速随机访问,查询快,增删慢
2.顺序存储,存放顺序与取出顺序一致,可以重复
3.arrayList是线程不安全的集合,对应的线程安全的集合是vector
4.默认容量为10,当超过容量时,会重新创建一个数组来存放元素,这个数组容量是原数组的1.5倍。
-
注意事项
1.它的父类AbstractCollection重写了toString方法,所以输出的不是地址
2.存储的数据类型必须为引用类型,基本类型需转换为包装类型才可以存储。
-
常用方法
get、set、判空、长度、删除、判断是否包含、判断某元素的索引、转换为数组
2.Vector
他是线程安全的,所以效率较低。与ArrayList的不同在于扩容的时候它会扩容为原来的两倍。且vector中提供了一个独特的取出方式Enumeration,他其实就是早期的迭代器。
3.LinkedList
-
数据结构
顺序表中的双向循环链表,每一个元素都有它的前驱和后继,在内存中位置不连续
-
特点
1.查询速度慢,增删速度快,只要把需要增删的元素的地址作为前一个和后一个元素的后继和前驱,所以很适合数据的插入和删除
2.有序链表,集合中的元素可以重复
3.线程不安全
4.因为是链表,所以不需要初始容量,也不需要扩容,只需要知道元素在内存中的地址就可以
-
常用方法
4.HashSet
-
数据结构
哈希表,底层采用的是通过一个键为指定的key,所有值都为同样的Object对象的HashMap来完成的。
-
特点
1.包含的元素都不重复,且取出无序
2.结合了数组和链表的优点。随机访问速度快,增删也快。
-
注意事项
1.往HashSet中存放javaAPI中提供的类时,不需要重写hashCode和equals方法,但在存放自定义的类型时,必须重写其中的hashCode和equals方法,从而实现其中元素的不重复。
-
常用方法
5.LinkedHashSet
继承自HashSet,提供了四个构造方法和一个迭代器,构造方法使用的是HashSet下new LinkedHashMap的方法,所以其底层是LinkedHashMap。可以实现存取有序的原因是因为每次存取的元素都有一个前驱和后继,指向着之前元素的地址和之后元素的地址,相当于又实现了一个单向链表。
6.TreeSet
-
数据结构
二叉树(红黑树),底层使用的TreeMap<E,Object>,与HashSet类似
-
特点
1.每增加一个元素都会进行排序,将对象插入到二叉树指定的位置
2.有序集合,存放的元素不重复
3.与哈希表相比,增删元素较慢,查询元素较快
-
注意事项
1.javaAPI中的类都可以进行默认的TreeSet排序,但自定义类的对象是不可以的。自己定义的类必须实现Compare接口,并且覆盖相应的compareTo方法,才能正常使用
2.在重写compareTo方法时,必须要返回相应的值才能使TreeSet按照一定的顺序来排序
3,.比较此对象与指定对象的顺序,如果该对象小于、等于或大于指定对象,则分别返回负整数、零和正整数。
7.HashMap
-
数据结构
在java7中,采用的数组加单向链表的数据结构。在java8中,底层采用的是数组+单向链表+红黑树的数据结构。当单向链表中的元素超过8之后,会将链表转换为红黑树。
-
特点
1.存取元素无序,且集合中的key不重复
2.增删速度快,java8改进之后,查询速度变快
3.初始数组容量,即桶的数量是2的幂,默认值为16。
4.装载因子为0.75,桶数扩容为之前的两倍也就是说在桶数组75%的位置已经填入元素,就会用双倍的桶数自动进行再散列
-
注意事项
1.可以存储null键,null值,但null键只能有一个,但null值可以有多个。
2.内部类EntrySet,内部接口Entry
-
常用方法
8.ConcurrentHashMap
-
数据结构
与hashMap相同,java8也改为了数组加单向链表加红黑树。整个ConcurrentHashMap是由一个个Segment(分段锁,也就是桶的锁)组成的,通过每一段锁的线程安全,保证全局的线程安全。它的并发性较高,最多支持桶数量,也就是分段锁数量的并发操作
9.HashTable
HashTable是遗留类,他的功能与HashMap类似,不同的是它继承Dictionary类,且它是线程安全的,并发性不如ConcurrentHashMap,所以在新代码中不再使用
10.TreeMap
-
数据结构
红黑树
-
特点
1.实现了SortedMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Itertor遍历TreeMap时,得到的记录是排过序的,如果使用自定义排序的映射,建议使用TreeMap
2.每次添加元素都会进行重新排序
3.查询的速度比HashMap要快
-
注意事项
1.对于插入的key,如果是javaAPI中的类,可以直接插入,如果是自定义的类,再插入之前必须实现Compareable接口或者在TreeMap中传入自定义的Comparator
11.LinkedHashMap
是HashMap的一个子类,保存了插入的顺序,即插入的时候实现了一个双向的链表。
迭代器
1.Iterator接口
-
概述
java中的迭代器与传统迭代器不同,传统迭代器是根据数组索引建模的。而java迭代器认为是位于两个元素之间,当进行迭代的时候,迭代器就越过下一个元素,并返回越过的那个元素的引用。所以每次进行迭代时,需要先判断是否还有元素,如果不判断的话就会报出空指针异常。同时在remove方法之前也必须先判断hasnext方法,否则不知道越过了哪个元素,就会报出IllegalStateException异常。
-
方法:hasNext()、next()、remove()、forEachRemaining()
-
注意事项
1.迭代器是用来描述集合中元素的位置的,那么依赖于位置的添加就得由迭代器来负责。
2.只有对自然有序的集合使用迭代器添加元素才有实际意义,所以在Iterator中没有添加元素的add方法,但是在其特定子类中ListItertaor迭代器中针对list集合添加元素设定了add方法。
2.ListIterator接口
-
概述
提供list集合在迭代中进行操作的迭代器,实现类是list集合中的内部类。
-
方法
添加了add方法和set方法。可以在迭代的过程中在迭代器位置添加值或者设置越过对象的值。同时还可以告知下一个元素和上一个元素的索引。
add方法依赖于迭代器的位置,而remove方法依赖于迭代器的状态。迭代器只有迭代之后才能remove,但不迭代也可以add。
对于数组转换后的list,其实不是真正的ArrayList,只是arrays工具类的内部类,没有重写add方法
-
注意事项:并发修改异常
1.在迭代器操作的过程中,如果集合本身调用自身的方法,对集合本身进行了修改,迭代器的设计可以检测到这种修改,由于这种修改是不可控的,那么这时候就会报出并发修改异常ConcurrentModificationException。
2.在listIterator迭代器操作的过程中,如果使用迭代器对当前集合进行修改,那么修改的迭代器只能有一个,且它必须在其他不能修改迭代器的最后。如果只是对集合进行迭代,可以存在多个迭代器。
3.检测集合修改的方法是迭代器维护一个独立的计数值,起初跟集合的计数值一样。如果集合被修改,此时集合的计数值就会加1,每次迭代判断迭代器的计数值与集合本身的计数值是否相等,如果不等就会报出并发修改异常。