Java学习(十三)集合
前言
集合的由来
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,Java就提供了集合类。
一、集合的由来及集合继承体系图
- 集合的由来
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,Java就提供了集合类。
集合框架被设计成要满足以下几个目标。
1.该框架必须是高性能的。基本集合(动态数组,链表,树,哈希表)的实现也必须是高效的。
2.该框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性。
3.对一个集合的扩展和适应必须是简单的。
- 集合和数组的区别
(1): 长度区别:
数组的长度是固定的而集合的长度是可变的
(2): 存储数据类型的区别:
数组可以存储基本数据类型 , 也可以存储引用数据类型; 而集合只能存储引用数据类型
(3): 内容区别:
数组只能存储同种数据类型的元素 ,集合可以存储不同类型的元素 - 集合继承体系图
1.Iterator接口
Iterator接口,这是一个用于遍历集合中元素的接口,主要包含hashNext(),next(),remove()三种方法。它的一个子接口LinkedIterator在它的基础上又添加了三种方法,分别是add(),previous(),hasPrevious()。
ConcurrentModificationException出现
我们用Iterator这个迭代器遍历采用hasNext方法和next方法,集合修改集合 会出现并发修改异常
原因是我们的迭代依赖与集合 当我们往集合中添加好了元素之后 获取迭代器 那么迭代器已经知道了集合的元素个数
这个时候你在遍历的时候又突然想给 集合里面加一个元素(用的是集合的add方法) 那迭代器不同意 就报错了
解决方案 我们用ListIterator迭代器遍历 用迭代器自带的add方法添加元素 那就不会报错了
a:迭代器迭代元素,迭代器修改元素(ListIterator的特有功能add)
b:集合遍历元素,集合修改元素
解决方案2 使用for循环遍历集合 添加元素 不会报错
为什么迭代器不定义成一个类 , 而是定义成一个接口?
---假设迭代器定义的是一个类,这样我们就可以创建该类的对象,调用该类的方法实现集合的遍历。但是呢?
我们想想,Java中提供了很多集合类,而这些集合类的数据结构是不同的,所以,存储的方式和遍历的方式应该是不同的。
进而它们的遍历方式也应该不是一样的,所以,就没有定义迭代器类。
---而无论你是哪种集合,你都应该具备获取元素的操作,并且,最好在辅助于判断功能,这样,在获取前,先判断。
这样就跟不容易出错。也就是说,判断功能和获取功能应该是一个集合遍历所具备的,而每种集合的方式又不太一样,
所以我们把这两个功能给提取出来,并不提供具体实现,这种方式就是接口。
那么,真正的具体的实现类在哪里呢?在真正的集体的子类中,以内部类的方式体现的。
2.Collection (集合的最大接口)
——List 可以存放重复的内容
——Set 不能存放重复的内容,所以的重复内容靠hashCode()和equals()两个方法区分
——Queue 队列接口
——SortedSet 可以对集合中的数据进行排序
Collection中的常用方法
boolean add(E e) - 用于将元素e放入当前集合中。
boolean addAll(Collection<? extends E> c)
- 用于将参数指定集合中的所有元素放入当前集合中。
boolean remove(Object o)
- 用于从当前集合中删除参数指定的元素。
boolean removeAll(Collection<?> c)
- 用于从当前集合中删除参数指定集合中的所有元素。
void clear()
- 用于将当前集合中的所有元素移除。
boolean contains(Object o)
- 用于判断当前集合中是否包含参数指定的单个元素。
- (o==null ? e==null : o.equals(e))
boolean containsAll(Collection<?> c)
- 用于判断当前集合中是否包含参数指定集合中的所有元素。
boolean isEmpty() - 用于判断当前集合是否为空。
int size() - 用于返回当前集合中元素的个数。
boolean retainAll(Collection<?> c)
- 用于获取当前集合和参数集合的交集并保留到当前集合中。
- 若当前集合中的内容发生了更改则返回true,否则返回false。
3、List的常用子类
——ArrayList 线程不安全,查询速度快
——Vector 线程安全,但速度慢,已被ArrayList替代
——LinkedList 链表结果,增删速度快
List集合常用的方法
void add(int index, E element)
- 用于将元素element插入到当前集合中index指向的位置。
boolean addAll(int index, Collection<? extends E> c)
- 用于将集合c中所有元素插入到当前集合中index指向的位置。
E remove(int index)
- 用于将index位置的元素从当前集合移除。
- 返回被删除的元素值,下标不合理时会产生下标越界异常。
E set(int index, E element)
- 使用element元素替换当前集合中index位置的元素,返回被替换的元素。
E get(int index)
- 用于返回当前集合中下标为index位置的元素。
List<E> subList(int fromIndex, int toIndex)
- 用于返回当前集合中从fromIndex(包含)到toIndex(不包含)之间的部分视图。
- 返回的集合和当前集合共用同一块内存区域。
4、Set接口及常用子类
Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。
——HashSet:底层数据结构是哈希表。是线程不安全的。不同步。
HashSet是通过元素的两个方法,hashCode和equals来保证元素唯一性
如果元素的HashCode值相同,才会判断equals是否为true。
如果元素的hashcode值不同,不会调用equals。
——TreeSet: 有序的存放,线程不安全,可以对Set集合中的元素进行排序
通过compareTo或者compare方法来保证元素的唯一性,元素以二叉树的形式存放。
Set接口常用的方法
该接口的常用方法参考Collection接口即可。
Iterator<E> iterator() - 用于获取当前集合中的迭代器,用于迭代集合中的所有元素。
- 迭代就是遍历/访问的意思,通俗来说,使用该方法的返回值可以访问集合任意元素
Iterator接口中的常用方法有:
boolean hasNext() - 用于判断当前集合中是否拥有可以访问的元素。
E next() - 获取一个元素返回后并指向下一个元素。
void remove() - 用于删除集合中刚刚获取到的元素。
5.Map接口
Correction、Set、List接口都属于单值的操作,而Map中的每个元素都使用key,value的形式存储在集合中。Map集合:该集合存储键值对。一对一对往里存。而且要保证键的唯一性。
Map接口的常用子类:
——HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的。将hashtable替代。
——TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。
Map接口常用的方法
V put(K key, V value) - 用于将参数指定的key和value组成一对放入当前集合中。
- 增加key和value时则返回null,修改key和value时则返回key之前对应的value。
V remove(Object key) - 用于从当前集合删除key关联的键值对。
- 若key不存在则返回null,否则返回key对应的value。
boolean containsKey(Object key)
- 用于判断当前集合中是否存在参数指定的key。
boolean containsValue(Object value)
- 用于判断当前集合中是否包含参数指定的value。
V get(Object key)
- 用于根据参数指定的key来返回对应的value。
Set<Map.Entry<K,V>> entrySet()
- 用于返回当前集合中包含映射关系的Set视图,通俗来说,就是把Map转换为Set。
Set<K> keySet()
- 用于返回当前集合中包含key的Set视图。
java.util.Map.Entry<K,V>接口代表键值对,提供的方法有:
K getKey() - 用于获取当前键值对中key的数值并返回。
V getValue() - 用于获取当前键值对中value的数值并返回。
6.集合工具类
Collections:集合框架的工具类。里面定义的都是静态方法。
Collections和Collection有什么区别?
Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。
它有两个常用的子接口,
——List:对元素都有定义索引。有序的。可以重复元素。
——Set:不可以重复元素。无序。
Collections是集合框架中的一个工具类。该类中的方法都是静态的。
提供的方法中有可以对list集合进行排序,二分查找等方法。
通常常用的集合都是线程不安全的。因为要提高效率。
如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。