1.集合类体系结构
以下是比较常用的集合类
2. Coolection接口
2.1 Collection 集合概述和使用
1)Collection集合概述
- 是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素
- JDK不提供此接口的任何直接实现,它提供更具体的接口(如Set和List)实现
2)创建Collection集合的对象 - 多态的方式
- 具体的实现类ArrayList、LinkedList等
举例:
package set;
import java.util.ArayList;
import java.util.Collection; //导包,在util包下
public class CollectionDemo
{
public static void main(String[] args)
{
Collection<String> c = new ArrayList<>(); //多态的方式创建Collection对象
//添加元素
c.add("hello");
c.add("friend");
//输出集合对象。 输出: [hello, friend]
System.out.println(c);
}
}
2.2 Collection 集合常用方法
方法名 | 说明 |
---|---|
boolean add(E e) | 添加元素 |
boolean remove(Object o) | 从集合中移除指定的元素 |
void clear() | 清空集合中的元素 |
boolean contains(Object o) | 判断集合中是否存在指定的元素 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中元素的个数 |
注:View->Tool Windows->structure或者Alt+7 然后输入类名或者接口名,可以看到它们的源码,大家可以试试Collection,看看以上方法都是怎么实现的。
2.3 集合的遍历
Iterator :迭代器,集合的专用遍历方式
- Iterator iterator() :返回此集合中元素的迭代器,通过集合的iterator()方法得到
- 迭代器是通过集合的iterator()方法得到的,所以我们说他是依赖于集合而存在的。
Iterator中的常用方法:
- E next(): 返回迭代中的下一个元素
- boolean hasNext(): 如果迭代具有更多元素,则返回true
Collection<String> c = new ArrayList<>();
...
Iterator<String> it = c.iterator();//通过集合对象获取迭代器对象
while(it.hasNext()){//判断是否还有元素
String s =it.next();//获取下一个元素,无法获取上一个元素(后面讲的ListIterator可以)
System.out.println(s);
}
}
注:
① Iterator需要导包 java.util.Iterator
②集合中的 Iterator< E > iterator() 方法返回此集合中元素的迭代器。
3. List接口
注:List接口实现了Collection接口
3.1 List集合概述和特点
- List 集合概述
- 有序集合(也成为序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过证书索引访问元素,并搜索列表中的元素。
- 与Set集合不同,列表通常允许重复的元素
- List集合特点
- 有序:存储和取出的元素顺序一致
- 可重复:存储的元素可以重复
3.2 List集合特有常用方法
方法名 | 说明 |
---|---|
void add(int index, E element) | 在此集合中的指定位置插入指定的元素 |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set(int index , E element ) | 修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 返回指定索引处的元素 |
3.3 并发修改异常
- ConcurrentModificationException
- 产生原因
- 迭代器遍历的过程中,通过集合对象修改了集合中的元素,造成了迭代器获取元素中判断迭代器获取元素中判断预期修改值和实际修改值不一致(这个可以通过Alt+7查看源码来看出)
- 解决方案
- 用for循环遍历,然后集合对象做对应的操作即可
举例:
- 用for循环遍历,然后集合对象做对应的操作即可
3.4 ListIterator迭代器
- ListIterator:列表迭代器
- 通过List集合的listIterator()方法得到,所以说它是List集合特有的迭代器。
- 用于允许程序员沿任意方向遍历列表的列表迭代器
- ListIterator中的常用方法
方法 | 说明 |
---|---|
void add(E e) | 将指定的元素插入列表(可选操作) |
boolean hasNext() | 如果此列表迭代器在向前遍历列表时具有更多元素,则返回 true |
E next() | 返回列表中的下一个元素并前进光标位置 |
boolean hasPrevious() | 如果此列表迭代器在反向遍历列表时具有更多元素,则返回 true |
E previous() | 返回列表中的上一个元素并向后移动光标位置 |
void remove() | 从列表中删除 next()或 previous() (可选操作)返回的最后一个元素 |
void set(E e) | 用指定的元素替换 next()或 previous()返回的最后一个元素(可选操作) |
3.5 增强for循环
- 增强for:简化数组和Collection集合的遍历
- 实现Iterable接口的类允许其对象成为增强型for语句的目标
- 它是JDK5之后出现的,其内部原理是一个Iterator迭代器
- 增强for的格式
- for(元素数据类型 变量名:数组或者Collection集合对象名){
//在此处使用变量即可,该变量就是元素
} - 范例:
int[] arr ={1,2,3,4,5};
for(int i : arr) {
System.out.println(i);
}
- for(元素数据类型 变量名:数组或者Collection集合对象名){
注:增强for循环内部原理是Iterator迭代器,所以以下代码照样抛出并发修改异常,需要用普通for替换
for(String s : list) {
if(s.equals("world")) {
list.add("javaee");
}
}
用三种方式遍历:
怎么选?
- 如果只是为了遍历,那么就选增强for,因为最方便
- 如果遍历时使用到索引或者代码出现并发修改异常,那只能选普通for
3.6 List集合子类特点
- ArrayList:底层数据结构是数组,查询快,增删慢
- LinkedList:底层数据结构是链表,查询慢,增删快
- ArrayList比较常用
3.7 ArrayList实现类
可调整大小的数组实现,能用上面的Collection接口、List接口的方法。
创建:
ArrayList< String > array= new ArayList<>();
常用方法:
方法 | 说明 |
---|---|
Boolean remove (object o); | 删除指定的元素,返回删除是否成功 |
E remove(int index); | 删除指定的索引处的元素,返回被删除的元素 |
E set(int index,E element); | 修改指定索引处的元素,返回被修改的元素 |
Int get(int index); | 返回指定索引处的元素 |
Int size(); | 返回集合中的元素个数 |
3.8 LinkedList实现类
创建:
LinkedList< String > linked= new LinkedList<>();
常用方法:
方法 | 说明 |
---|---|
void add(int index, E element) | 将指定元素插入此列表中的指定位置。 |
boolean add(E e) | 将指定的元素追加到此列表的末尾。 |
void addFirst(E e) | 在此列表的开头插入指定的元素。 |
void addLast(E e) | 将指定的元素追加到此列表的末尾。 |
E getLast() | 返回此列表中的最后一个元素。 |
E getFirst() | 返回此列表中的第一个元素。 |
E removeFirst() | 从此列表中删除并返回第一个元素。 |
E removeLast() | 从此列表中删除并返回最后一个元素。 |
4.Set接口
注:Set接口实现了Collection接口
4.1 Set集合概述和特点
- 不包含重复元素的集合。
- 更正式地说,集合不包含元素对e1和e2 ,使得e1.equals(e2)和最多一个null元素。
- 没有带索引的方法,所以不能用普通for循环遍历
4.2 哈希值
- 哈希值是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
- Object类中有一个方法可以获取对象的哈希值
- public int hashCode(): 返回对象的哈希码值
- 对象的哈希值特点
- 同一个对象多次调用hashCode()方法返回的哈希值是相同的
- 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同
4.3 HashSet类
4.3.1 HashSet集合特点
- 底层数据结构是哈希表
- 对集合的迭代顺序不做任何保证,也即是说不保证存储和取出的元素顺序一致
- 没有带索引的方法,所以不能使用普通for循环遍历
- 由于是Set集合,所以是不包含重复元素的集合
4.3.2 HashSet集合保证元素唯一性源码分析
HashSet集合添加一个元素的过程:
HashSet集合存储元素:
- 要保证元素唯一性,需要重写hashcode()和equals()
4.3.2 哈希表
哈希表在JDK8之前,底层采用数组+链表实现,可以说是一个元素为链表的数组;在JDK8以后,在昌都较长的时候,底层实现了优化。
注:
- 在IDEA下,按下Alt+insert 选择 equals() and hashcode() 一直点next 就可以自动重写此方法了。(重写可以避免相同的元素重复出现)
4.4 TreeSet类
4.4.1 TreeSet集合特点
- 元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
- TreeSet() : 根据其元素的自然排序进行排序
- TreeSet(Comparator comparator) : 根据指定的比较器进行排序
- 没有带索引的方法,所以不能使用普通的for循环遍历
- 由于是Set集合,所以不包含重复元素的集合
注:这里的自然排序在整数中就是自然数从小到大的排序
4.4.2 自然排序Comparable的使用
- 用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
- 自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(T o)方法
- 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写。
public Student(){
@Override
public int compareTo(Student s) {
int num = this.age - s.age;
//年龄相同时,按照姓名的字母顺序排序
int num2 = num==0?this.name.compareTo(s.name):num;
return num2;
}
}
按照以上方法重写compareTo()方法之后以下代码及结果为:
5.比较器排序Comparator的使用
- 用TreeSet集合存储自定义对象,带参构造方法适应的是比较器排序对元素进行排序
- 比较器排序,就是让集合构造方法接受Comparator的实现类对象,重写compare(T o1,T o2)方法
- 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
举例:
① 需求:
② 代码:
③ 结果:
④ 分析:
- 先用getSum()方法判断总分,num = s2.getSum() - s1.getSum(); 显然这样是按照总分的降序排序。
- num2 =…表示当总分一样的情况下,按照语文成绩的升序排序。
- num3 =…表示语文成绩也相同的情况下(此时数学成绩肯定相同,因为总分相同),看看名字,如果有名字相同的话,这说明是同一个人重复add(),则num3==0,也就是return 0,当compare()方法返回0时,说明跟该对象内容一样的应一个对象已经在集合里,所以add()方法不添加此对象到TreeSet里。
5.其他内容
5.1 使用Collection对ArrayList集合排序的案例
需求: ArrayList存储学生对象,使用Collection对ArrayList进行排序
要求:按照年龄从小到大排序,年龄相同时,按照姓名的的字母顺序排序
5.2 一些知识(待更新)
- Collections有一个这样的方法:static void shuffle(List<?> list) 使用默认的随机源随机置换指定的列表。
:
:
:
主页还有更多Javase相关的笔记,欢迎大家指点评论