复习总结七
总结
Java的集合类都在java.util包中,使用前需要导入:import java.util.*;
单列集合(Collection)
- Collection是单列集合的根接口,实现了该接口的类称为单列集合
- List 子接口: 实现List接口的集合称为List集合
- List集合的特点是存储的元素有序且可重复
- ArrayList
- LinkedList
- Set 子接口: 实现Set接口的集合称为Set集合
- Set集合的特点是存储的元素无序且不可重复
- HashSet
- TreeSet
- Queue 子接口
- List 子接口: 实现List接口的集合称为List集合
有序是指元素的存储位置有顺序,不是指元素按大小有序
双列集合(Map)
- Map是双列集合类的根接口,实现了该接口的类称为双列集合
- HashMap
- TreeMap
- HashTable
- 双列集合用于存储具有键(Key)—值(Value)对应关系的元素,每个元素由键和值组成一个二元组<Key,Value>
键用来唯一标识元素,可以通过键找到值
List
- 实现List接口的集合称为List集合,也可称为列表,主要有ArrayList和LinkedList。
- List集合允许出现重复元素,元素以线性方式存储,可以通过索引(下标)来访问。List集合的存储顺序和遍历顺序一致。
ArrayList
- 在ArrayList集合的内部封装了一个数组,初始长度的默认值是10,也可以在创建集合对象时指定数组的初始长度。
- ArrayList集合的add(Object o)方法将元素添加到列表的尾部,而add(int index,Object o)方法将元素插入列表的指定位置index处
- 删除元素时,ArrayList集合将被删除元素之后的元素都向前移一个位置以填补空位
- 将元素插入指定位置时,会将该位置的元素以及后面的元素都向后移一个位置
- 更新操作的效率低
- 查询操作的效率高
集合和数组一样,索引的取值范围是从0开始,到size-1为止(size是集合中的元素个数),不能超出此范围,否则会引发异常。
LinkedList
- 在LinkedList集合内部维护了一个双向链表,每个元素都存有分别指向前一个元素和后一个元素的引用,从而将所有的元素链接起来
调用LinkedList的add(int index,Object o)方法添加元素,需要先找到索引index指示的位置,所以时间复杂度是O(n)。
调用add(Object o)、addFirst(Object o)、addLast(Object o)等方法添加元素,因为位置是已知的,只需要添加新节点,所以时间复杂度是O(1)
Iterator
- Iterator接口也是Java集合框架中的一员,也称为迭代器
- 集合的iterator()方法返回一个Iterator接口的实现类对象,用于遍历集合中的元素
- Iterator 方法:
- boolean hasNext(): 判断是否还有下一个元素,如果是,返回 true,否则返回false。
- Object next(): 访问下一个元素并返回该元素的引用。调用next()方法访问下一个元素时,要保证该元素的存在,否则会抛异常
- void remove(): 删除刚访问过的元素
- 在使用Iterator迭代器遍历集合的过程中,如果调用集合的remove()或add()方法执行删除或添加操作,那么再继续遍历就会引发异常
- 删除某个元素后跳出循环不再继续迭代
1
2
3
4if("Annie".equals(obj)) {
list.remove(obj);
break;
}- 可以使用Iterator迭代器自身的删除方法,也就是将代码list.remove(obj) 替换成it.remove()
1
2
3if("Annie".equals(obj)) {
it.remove();
}
ListIterator接口
- 为了使迭代方式多样化,既可以正向迭代,也可以反向迭代,Java提供了ListIterator接口
- 它是Iterator的子接口,新增了一些方法
- 集合的listIterator()方法返回一个ListIterator迭代器对象
注意,List集合实现了ListIterator接口,而Set集合没有实现ListIterator迭代器
- ListIterator新增的方法主要用于反向迭代,此外还提供add()方法用于在遍历的过程中添加元素
- 由于ListIterator是Iterator的子接口,因此是双向迭代器
- 在遍历集合的期间,通过Iterator迭代器只能删除元素,而通过ListIterator迭代器既可以添加也可以删除元素
- listIterator(int index)方法的index参数指定迭代的起始位置,正反向迭代都可以执行,index的范围是0到list.size();
- 无参数的listIterator()方法,则相当于调用listIterator(0)
foreach
foreach循环除了用于遍历数组外,也可以用于遍历集合,是一种更加简洁的for循环,也称增强型for循环
1 | for(集合中的元素类型 临时变量 : 容器) { |
与for循环相比,foreach循环不需要获得容器的长度,也不需要通过索引访问容器中的元素,而是自动的遍历容器中的每个元素
foreach循环只能用于遍历访问,不能用于修改集合或数组中的元素。
因为临时变量保存的是所访问元素的引用,修改临时变量,只是修改了临时变量的引用,而不是修改所引用元素的值
Set
- 与List集合不同,Set集合中的元素无序、不允许重复
- 主要实现类有HashSet和TreeSet
- HashSet内部维持一个哈希表结构,根据对象的哈希值来确定元素的存储位置
- TreeSet内部则维持一个二叉排序树,对存入集合中的每个元素进行排序
HashSet
- 当使用HashSet的add()方法添加一个元素时,首先调用该元素的hashCode()方法获得对象的哈希值,然后根据哈希值确定一个存储位置
- 如果这个位置上没有元素,直接将该元素存入此位置
- 如果这个位置上已存入元素,则调用该元素的equals()方法依次和已存入元素进行比较
- 比较结果均为false说明不存在重复元素,则将该元素存入这个位置
- 若和某个已存入元素的比较结果为true,说明该元素和这个已存入元素的值相等,则抛弃该元素
由于哈希表冲突现象的存在,哈希值相同的对象未必就是值相同的对象
当向HasheSet集合中存入元素时,为了保证HasheSet正常工作,存入的对象应当重写Object根类的hashCode()和equals()方法
1 |
|
TreeSet
- TreeSet集合采用二叉排序树来存储元素,会对存入的元素进行排序
- 因为要排序,所以要比较元素的大小,这就需要元素实现Comparable接口,或者给集合传入一个自定义的Comparator比较器
- TreeSet集合同样不允许存入重复元素,若插入重复的新元素则会抛弃
- 和HashSet集合不同,TreeSet集合是通过比较大小来判断是否是重复元素,大小相同元素的就认为是重复元素
- 通过Iterator迭代器遍历TreeSet集合时,输出的字符串按字典序形成有序序列
- 因为TreeSet集合在内部对元素进行排序,而String类实现的Comparable接口是按字典序比较大小的
TreeSet集合用Iterator迭代器遍历形成的元素序列都是有序序列
- 往TreeSet集合中添加的元素需要实现Comparable接口,否则无法比较大小,没法进行排序
- 可以自己为TreeSet集合定义一个比较器,即定义一个Comparator接口的实现类,把该实现类的对象输入TreeSet集合作为比较器
Map
实现了Map接口的集合称为Map集合,也叫双列集合,常用的有HashMap和TreeMap(提示:HashSet由HashMap实现,TreeSet由TreeMap实现)
双列集合存储的每个元素都包含一个键Key和一个值Value,从键到值构成一个映射。键具有唯一性,可以唯一确定一个元素
- 访问Map集合中的元素时,只要指定了Key,就能找到对应的值
- Map集合添加元素使用put(Object k, Object v)方法,查找元素使用get(Object k)方法
HashMap
HashMap内部维持一个Hash表,用于存储具有键—值映射关系的数据
- HashMap集合不允许出现重复的键,如果出现重复的键,则认为是重复的元素,那么新元素会覆盖键相同的旧元素
- 通过重写键的hashCode()方法来计算键的hash码,通过重写键的equals()方法来判断键是否相同,如果不重写,就会调用从Object类继承的这两个方法
- 往HashMap集合添加元素的过程与HashSet集合类似
- 首先调用键的hashCode()方法计算键的hash码,根据hash码计算出存储位置
- 如果在该位置上没有元素就直接存入
- 如果该位置上已有元素,则调用键的equals()方法依次和这些已有元素的键进行比较
- 如果比较结果均为false,就将该元素存入当前位置,否则说明有重复元素,则用新元素覆盖键相同的旧元素
三种遍历
1 | Map map = new HashMap(); |
1 | Map map = new HasMap(); |
1 | Map map = new HasMap(); |
TreeMap
- 用来存储由键-值对构成的元素,不允许出现重复的键
- TreeMap集合使用二叉排序树来存储元素,元素是按键的大小顺序排列的
- 元素的键要实现Comparable接口或者实现键的自定义比较器Comparator,以便能对键比较大小
- 键大小相同的元素即认为是重复元素,对于重复元素,也是
新元素覆盖旧元素
- TreeMap集合的遍历方式与HashMap集合相同,也是那三种方式
工具类
- java.util包提供了工具类Collections用来操作集合
- Collections类封装了大量静态方法对集合中的元素进行排序、查找和修改等操作
排序操作
- static void reverse(List list):反转List集合中的元素顺序
- static void sort(List list):根据自然序对集合中的元素进行排序
- static void shuffle(List list):对List集合中的元素进行随机排序(洗牌)
查找替换
- static int binarySearch(List list, Object key):使用二分查找法搜索集合中是否存在指定值为key的元素,返回该值的索引
- static Object max(Collection col):返回集合中最大的元素
- static Object min(Collection col):返回集合中最小的元素
- static boolean replaceAll(List list, Object oldVal, Object newVal):用新值newVal取代集合中的所有旧值oldVal
- static void swap(List list, int i, int j):交换集合中位置i和位置j处的元素
Arrays
java.util包还提供了用于操作数组的工具类Arrays,封装大量的静态方法用于操作数组
排序
- 可以使用Arrays的sort()方法实现数组的排序。
- 如果数组的元素是字符型、整型或浮点型等数值类型,则按值的大小进行排序。
- 如果数组的元素是对象,则所有元素都必须实现 Comparable 接口(按该接口的compareTo方法比较大小),否则无法排序。
查找
- binarySearch()方法使用二分查找法搜索指定值的位置,需要先对数组排序。
- 如果数组的元素是对象,还需要自己实现比较器:int binarySearch(Object[] a, Object key, Comparator c),这里参数c是一个自定义的Comparator比较器。
把数组转换为字符串
- 使用Arrays的toString()方法将数组存储的数据转换成字符串形式:[“元素1”, “元素2”, …],这样就可以直接打印输出数组了。
- 如果数组的元素是八种基本类型,没有任何问题;如果数组的元素是对象,则要调用对象的toString()方法实现转换,所以元素必须正确的重写Object类的toString()方法
拷贝元素
Arrays工具类的copyOfRange(Object[] original, int from, int to)方法将数组中指定范围的元素复制到一个新的数组中,该方法中参数original表示被复制的数组,from表示被复制元素的初始索引(包括),to表示被复制元素的最后索引(不包括)
填充元素
可以使用Array的fill(Object[] a, Object val)方法将指定的值赋给数组中的每一个元素