类集
Java类集构造图:
类集:我们可以理解为Java对各种数据结构成熟的实现
(为什么要引进类集?因为我们要使用不同的数据结构来更好更方便的存储数据)
由图可以看出Collection,Map和Iterator是最重要的接口。
(Collection是存储单值的,Map是存储双值的,而Iterator是遍历数据的最优实现)
使用集合框架的原因
(1)为什么出现集合类?
面向对象对事物的体现都是以对象的形式,为了方便对多个对象的操作,就对对象进行存储。
集合就是存储对象最常用的一种方式.
(2)数组和集合都是容器,两者有何不同?
**数组长度固定,而集合长度是可变的
**数组值可以存储对象,还可以存储基本数据类型;而集合只能存储对象
**数组存储数据类型是固定的,而集合存储的数据类型不固定
(3)集合类的特点:
集合只能存储对象
集合的长度是可变的
集合可以存储不同类型的对象
Collection接口
Collection 接口是在整个 Java 类集中保存单值的最大操作父接口,里面每次操作的时候都只能保存一个对象的数据。(集合存的是对象,也就是说存基本数据类型的时候,会自动装箱成引用数据类型)此接口的常用方法如下所示。
1 public boolean add(E e)
重要 向集合中插入一个元素
2 public boolean addAll(Collection<? extends E> c)
普通 向集合中插入一组元素
3 public void clear()
普通 清空集合中的元素
4 public boolean contains(Object o)
普通 查找一个元素是否存在
5 public boolean containsAll(Collection<?> c)
普通 查找一组元素是否存在
6 public boolean isEmpty()
普通 判断集合是否为空
7 public Iterator iterator()
重要 为 为 Iterator 接口实例化
8 public boolean remove(Object o)
普通 从集合中删除一个对象
9 boolean removeAll(Collection<?> c)
普通 从集合中删除一组对象
10 boolean retainAll(Collection<?> c)
普通 判断是否没有指定的集合
11 public int size()
重要 求出集合中元素的个数
12 public Object[] toArray()
普通 以对象数组的形式返回集合中的全部内容
13 T[] toArray(T[] a)
普通 指定操作的泛型类型,并把内容返回
14 public boolean equals(Object o)
普通 从 Object 类中覆写而来
15 public int hashCode()
普通 从 Object 类中覆写而来
但是,在开发中不会直接使用 Collection 接口。而使用其操作的子接口:List、Set。
- list接口有序,允许有重复的元素;
- set接口无序,不允许有重复的元素;
List
列表,元素是有序的(元素带角标索引),可以有重复元素,可以有null元素。
对已有的 Collection 接口进行扩充的方法有
- public E get(int index) 根据索引位置取出每一个元素
- public ListIterator listIterator() 返回 ListIterator接口的实例
了解了 List 接口之后,那么该如何使用该接口呢?需要找到此接口的实现类,常用的实现类有如下几个:
· ArrayList(95%)、Vector(4%)、LinkedList(1%)
-
ArrayList(很常用)
- 底层的数据结构是动态数组数据结构,特点是查询速度快(因为带下标),
- 但是增删速度稍慢,因为当元素多时,增删一个元素则所有元素的下标都得改变
- 线程不同步。默认长度是10,当超过长度时,按50%动态扩容延长集合长度。
-
Vector
- Vector功能跟ArrayList功能一模一样,已被ArrayList替代。
- 底层数据结构也是数组数据结构.特点是查询和增删速度都很慢。
- 默认长度是10,当超过长度时,按100%延长集合长度;当然我们可以指定动态扩容的数量。
- 线程同步安全,在不考虑线程的情况下,用ArrayList替代。
-
LinkedList
- 底层数据结构是双向链表数据结构
- 查询速度慢,因为每个元素只知道前面一个元素,但增删速度快 因为元素再多,增删一个,只要让其前后的元素重新相连即可,线程是不同步的。
- 它有一些特别的方法可以模拟队列和栈的数据结构
-
压栈 :E push() <==> addFirst(E e) 在此列表的开头插入指定的元素。
-
弹栈 :E pop() <==> E removeFirst() 从此列表中删除并返回第一个元素。
一般情况下,使用哪种List接口下的实现类呢? 如果要求增删快,考虑使用LinkedList 如果要求查询快,考虑使用ArrayList 如果要求线程安全,考虑使用Vector。
-
Iterator迭代器
Iterator迭代器分为两种:一种是用来迭代Collection下的所有集合的Iterator迭代器;一种是只迭代List集合的ListIterator迭代器。
迭代器:Iterator(Map集合没有迭代器)
(1)迭代器就是取出集合元素的方式
(2)迭代器的作用
因为每个集合中元素的取出方式都不一样,于是就把元素的取出方式进行抽取,并定义在集合内部,
这样取出方式就可以直接访问集合内部的元素;
而每个容器的数据结构不同,所以取出动作的细节也不一样,但是有共性内容:判断和取出。
那么就将共性内容进行抽取,从而形成了接口Iterater
(3)获取迭代器的方法:
Iterator<E> iterator() 返回在此 collection 的元素上进行迭代的迭代器。
Iterator<E> iterator() 返回在此 set 中的元素上进行迭代的迭代器。
(3)迭代器方法:
boolean hasNext() 如果仍有元素可以迭代,则返回 true。
E next() 返回迭代的下一个元素。
void remove() 从迭代器指向的collection中移除迭代器返回的最后一个元素(可选操作)。
列表迭代器:ListIterator
(1)List集合特有的迭代器ListIterator是Iterator的子接口,在迭代时,不可以通过集合对象的
方法操作集合中的元素,因为会发生ConcurrentModificationException(当方法检测到对象的并发修改,
但不允许这种修改时,抛出此异常)
(2)Iterator方法有限,只能对元素进行判断、取出和删除的操作
ListIterator可以对元素进行添加和修改动作等。
(3)获取列表迭代器方法:
ListIterator<E> listIterator() 返回此列表元素的列表迭代器(按适当顺序)。
ListIterator<E> listIterator(int index)
返回此列表中的元素的列表迭代器(按适当顺序),从列表中指定位置开始。
(4)列表迭代器方法:
void add(E e) 将指定的元素插入列表(可选操作)。
boolean hasPrevious() 如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。
int nextIndex() 返回对 next 的后续调用所返回元素的索引。
E previous() 返回列表中的前一个元素。
int previousIndex() 返回对 previous 的后续调用所返回元素的索引。
void set(E e) 用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。
注意:集合使用迭代器遍历元素,而数组不能使用迭代器但可以使用foreach来遍历元素。(foreach的作用就是遍历数组和集合的数据的)
HashMap
影响HashMap性能的主要就是它的初始容量和散列因子(负载因子):
- 对于初始容量的描述:
- 1.初始容量给的过小而存的数据过大,HashMap为了存储数据就会频繁的散列,从而导致了大量内存空间的浪费。
-
所以初始容量要给的合理,避免频繁的散列情况,减少哈希表的重建次数,提高性能。
- 对于散列因子的描述:
- 1.散列因子过大时,哈希桶的利用特别好,节省了内存空间(减少了散列次数),但是查找数据慢。
- 2.散列因子过小时,哈希桶中存的数据少,浪费空间(散列次数多),但是查询数据的效率很高。
使用HashMap存储自定义类型
一定不要随意的改变键值的数据。
若是改变了键值,就会很难再找到这个数据。因为HashMap的存取数据都是要根据键的哈希值来完成的,一旦改变键值的数据,那么会发生存储数据的位置(哈希值)与取出数据的位置(哈希值)不一致,导致找不到这个数据。
集合在jdk9的新特性
可以创建一个固定长度存储少量数据的集合。(不可改变长度的集合),注意只有在lis,tset,map这三个接口有这个方法。