集合
集合
(一). 集合相关
1.1 为什么出现集合类?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象进行操作,就对对象进行存储。集合就是存储对象常用的一种方式。
1.2 定义
所有抽象出来的数据结构和操作(算法)统称为Java集合框架,简称JCF。Java的集合框架主要由一组用来操作对象的接口组成,不同接口描述一组不同数据类型。核心接口主要有:Collection、List、Set、Map.
1.3 数组与集合同是容器,有什么不同?
数组虽然也可存储对象,但是数组长度是固定的,而集合的长度是可变的。
数组中可以存储基本数据类型,但是集合只能存储对象。
1.4 集合类的特点
集合长度可变;只能存储对象,不能存储基本数据类型值;集合可以存储不同类型的对象。
1.5 简化框架图
(二).集合中的接口及实现类
2.1 Collection接口
- Collection接口是集合框架的基础,用于表示对象的集合。该接口中声明了所有集合都将拥有的核心方法,例如添加、删除等,并提供了一组操作成批对象的方法,还提供了查询操作,如判断是否为空的方法。
- 常用方法
boolean add(E obj)————将obj加入到调用类集中,成功返回true
boolean addAll(Collection<? extends E> c)————将c中的所有元素都加入到类集中,操作成功返回true
void clear()————从类集中删除所有元素
boolean contains(Object obj)————确定类集中包含指定的对象obj,成功返回true
boolean containsAll(Collection<?> c)———— 确定类集中是否包含指定集合的所有对象,存在返回true
int hasCode()————返回调用类集的散列码
boolean isEmpty()————判断类集是否为空,若为空则返回true
Iterator<E> iterator()————返回类集的迭代接口
boolean remove(Object obj)————从类集中删除obj实例
boolean removeAll(Collection<?> c)————从类集删除包含在c中的所有元素
boolean retainAll(Collection<?> c)————删除类集中除了包含在c中的元素之外的全部yuans
int size()————返回类集中元素的个数
Object[] toArray()————以数组形式返回类集中的所有对象
3.在使用Collection时需注意:
当企图将一个不兼容的对象加入一个Collection中时, 将产生ClassCastException异常;
Collection中没有提供取得某个元素的方法,只能通过iterator()遍历元素
2.2 List接口
- List接口继承Collection接口,元素允许重复,以元素添加的次序来放置元素,不会重新排列。(有序)。该接口不但能队列表的一部分进行处理,还允许针对位置索引的随机操作。常用的List实现类有ArrayList和LinkedList
- 常用方法
void add(int index,E element)————在指定位置index上添加元素element。
boolean addAll(int index,Collection<? extends E> c)————将集合c中的所有元素添加到指定位置index
E get(int index)————获取,返回List中指定位置的元素,
int indexOf(Object o)————返回第一个出现元素o的位置,否则返回-1
int lastIndexOf(Object o)————返回最后一个出现元素o的位置,否则返回-1
E remove(index)————删除指定位置上的元素
E set(int index,E element)————替换,用元素element替换位置index上的元素,依旧返回旧的元素
ListIterator<E> listIterator()————返回一个列表迭代器,用于访问列表中的元素
ListIterator<E> listIterator()————返回一个列表迭代器,用于从指定位置index开始访问列表中的元素
List<E> subList(int start,int end)————返回从指定位置start(包含)到end(不包含)范围中各个元素的列表 - 注意事项
如果使用无效索引,出IndexOutOfBoundException异常
2.2.1 List的实现类——ArrayList
从其命名中可以看出,ArrayList是以一种类似数组的形式进行存储,其内部封装有动态数组,因此它的随机访问速度极快。
- 常用方法
ArrayList()————构造方法,用于建立一个空的数组列表
ArrayList(Collection<? extends E> c)————构造方法,用于建立一个用集合c数据初始化的列表
ArrayList(int capacity)————构造方法,用于建立一个指定初始容量的数组列表
void ensureCapacity(int minCapacity)————增加此ArrayList对象的容量,以确保它至少能够容纳minCapacity个元素数
void trimToSize()————调整ArrayList对象的容量为列表当前大小。即释放没用的空间,应用程序可使用此操作来操作最小化ArrayList对象存储空间。
2.2.2 List的实现类——LinkedList
LinkedList的内部实现基于链表,适合于频繁的数据增删操作,经常用于构造堆栈Stack、队列Queue
- 常用方法
LinkedList()————构造方法,用于建立一个空的数组列表
LinkedList(Collection<? extends E> c)————构造方法,用于建立一个用集合c数据初始化的数组列表
void addFirst(E obj)————向列表头部增加一个元素
void addLast(E obj)————向列表尾部增加一个元素
E getFirst()————获取列表的第一个元素
E getLast()————获取列表的最后一个元素
E removeFirst()————移除列表的第一个元素
E removeLast()————移除列表的最后一个元素
2.3 Set接口
Set接口继承Collection接口,Set中的对象元素不能重复,其元素添加后不保证与添加的顺序一致,无序。Set接口没有引入新方法,所以Set就是一个Collection,只是其行为不同。常用实现类有HashSet类和TreeSet类。
2.3.1 Set实现类——HashSet
HashSet能够快速定位一个元素,放到HashSet中的对象一般需要重写hashCode()方法。该结构使用散列表进行存储。再散列中,一个关键字的信息内容被用来确定唯一的一个值,成为散列码(hash code)。而散列码被用来当做与关键字相连的数据的存储下标。关键字到其散列码的转换是自动执行的。散列法的优点在于即使对于大的集合,一些基本操作如add、contains、remove和size方法的平均运行时间保持不变。
- 常用构造方法
HashSet()————构造一个默认的散列集合
HashSet(Collection<? extends E> c)————用c中的元素初始化散列集合
HashSet(int capacity)————初始化容量为capacity的散列集合
HashSet(int capacity,float fill)————初始化容量为capacity,填充比为fill的散列集合
2.3.2 Set实现类——TreeSet
TreeSet是用树结构来进行存储,对象按升序存储,访问和检索速度快。在存储了大量多的需要进行快速检索排序信息的情况下,TreeSet是一个很好的选择。
要注意:TreeSet元素按照字符串顺序也就是字典顺序排列,TreeSet将放入其中的元素按序存放,这就要求放入其中的对象是可排序的。集合框架中提供了用于排序的两个实用接口:Comparable和Comparator。一个可排序的类应该实现Comparable接口。如果多个类具有相同的排序算法时,或需为某个类指定多个排序依据,可将排序算法抽取出来,通过扩展Comparable接口的类实现即可。
在不指明排序依据的情况下,添加到TreeSet中的对象需要实现Comparable接口。
- 常用构造方法
TreeSet()————构造一个空的TreeSet
TreeSet(Collection<? extends E> c)————构造一个包含c的元素的TreeSet
TreeSet(Comparator<? super E> comp)————构造由comp指定的比较依据的TreeSet
TreeSet(SortedSet<E> sortSet)————构造一个包含sortSet所有元素的TreeSet
2.4 Map接口
Map接口没有继承Collection接口。Map接口用于维护键/值对的集合。Map容器中的键对象不允许重复,而一个值对象又可以是一个Map,依次类推,这样就可以形成一个多级映射。
Map是一种把键对象和值对象进行关联的容器,Map容器中的键对象不允许重复。Map中提供了Map.Entry接口,通过Mapde entrySet方法返回一个实现Map.Entry接口的对象集合,使得可以单独操作Map的项(键/值对),在Map中的每一个项,就是一个Map.Entry对象,通过遍历每一个Entry,可以获得每一个条目的键或值,并对值进行修改。常用的实现类有HashMap、TreeMap。
- Map.Entry常用方法
K getKey()————返回该项的键
V getValue()————返回该项的值
int hashCode————返回该项的散列值
boolean equals(Object obj)————判断当前项与指定的obj是否相等
V setValue(V v)————用v覆盖当前项的值,并且返回旧值 - Map的方法
void clear()————删除所有的键/值对
boolean containsKey(Object key)————判断Map中是否包含了关键字为key的键/值对
boolean containsValue(Object key)————判断Map中是否包含了值为key的键/值对
Set<Map,Entry<K,V> > entrySet()————返回Map中项的集合,集合对象类型为Map.Entry
V get(Object key)————获取键为key对应的值对象
int hasCode()————返回Map的散列码
boolean isEmpty()————判断Map是否为空
Set<K> keySet()————返回Map中关键字的集合
V put(K key,V value)————返回键值对为key-value的项,如果key值已经存在,则覆盖并返回旧值,否则作为增加操作,返回null
void putAll(Map<? extends K, ? extends V> m)————将m的项全部放入到当前Map中
V remove(Object key)————移除键为key对应的项
int size()————返回Map中项的个数
Collection<V> values()————返回Map中值的集合 - 需要注意的是,Map不是Collection,但可以将Map转化为Collection,Map提供了用于转换为集合的三个方法:
entrySet():返回一个包含了Map中元素的集合,每个元素都包括键值对
keySet():返回键的集合
values():返回值的集合
2.4.1 Map实现类——HashMap
HashMap类使用散列表实现Map接口。散列映射并不保证它的元素顺序,元素加入散列映射的顺序并不一定是他们被迭代方法读出的顺序。HashMap允许使用null键和null值。
2.4.2 Map实现类——TreeMap
TreeMap类使用树实现Map接口。TreeMap按顺序存储“键/值”对,同时允许快速检索。值得注意的是,不像是散列映射,TreeMap保证他的元素按照键升序排序
- 常用构造方法
TreeMap()————构造一个缺省的TreeMap
TreeMap(Comparator<? super K> comp)————构造指定比较器的TreeMap
TreeMap(Map<? extends K,? extends V> m)————使用已有的Map对象m构造TreeMap
TreeMap(SortedMap<K,? extends V> m)————使用已有的SortedMap对象m构造TreeMap
2.5 迭代器接口
它的功能与遗留的Enumeration类似,但更容易掌握,功能也更强大。Iterator接口中的方法能以迭代方式逐个访问集合中各个元素,并安全的从Collection中删除元素。
- Iterator常用方法
boolean hasNext()————判断是否存在另一个可访问的元素,如存在返回true
E next()————返回要访问的下一个元素。如果到达集合结尾,则抛出NoSuchElementException异常
void remove()————删除上次访问返回的对象。本方法必须紧跟在一个元素的访问后执行。如果上次访问后集合已被修改,方法将抛出IllegalStateException - 注意:可以使用Collection接口的Iterator方法获取当前集合的Iterator操作对象
2.5.1 ListIterator接口
ListIterator接口继承Iterator接口,是列表迭代器,用以支持添加或更改底层集合中的元素,允许程序员双向访问、修改列表。ListIterator没有当前位置,光标位于调用previous和next方法返回的值之间,是一个长度为n的列表,有n+1个有效索引值
- ListIterator常用方法
void add(E o)————将对象o添加到当前位置的前面
void set(E o)————用对象o替代next或previous方法访问的上一个元素
boolean hasPrevious()————判断向后迭代时是否有元素可以访问
E previous()————返回上一个对象
int nextIndex()————返回下次调用next方法时将返回的元素的索引
int previousIndex()————返回下次调用previous方法时将返回的元素的索引
(三)集合技巧
3.1 记忆技巧
判断元素需要唯一么?
——需要:Set
——需要制定顺序么?
——需要:TreeSet(按照字典顺序,即指定方式排序)
——不需要:HashSet(无序)
——如果需要一个和存储一致的顺序:LinkedHashSet
——不需要:List
——需要频繁增删么?
——需要:LinkedList
——不需要:ArrayList
TreeSet、HashSet、LinkedList、ArrayList,其后缀名就是该集合所属体系,前缀名就是该集合的数据结构
看到Array,就要想到数组,查询快、有角标;
看到Link,就要想到链表,增删快,就要想到增、删方法,add、remove、get
看到Hash,就要想到哈希表,想到唯一性,想到元素需要覆盖hashcode方法及equals方法
看到Tree,就要想到二叉树,想到排序,想到两个接口Comparable、Comparator
通常这些容器都是不同步的,同步的就是Vector,但是相应的效率是非常慢的。
3.2 要注意的问题
简述Collection和Collections的区别?
Collection接口是集合框架的基础,用于表示对象的集合。该接口中声明了所有集合都将拥有的核心算法
Collections是集合框架中的辅助类,提供了一个Collection类型的容器,诸如排序、查找、复制、填充等非常有用的方法
Collections和Arrays的区别?
Collections是集合框架中的辅助类,提供了一个Collection类型的容器,诸如排序、查找、复制、填充等非常有用的方法。
Array也是一个很实用的辅助类,提供了针对数组的类似操作的方法。