集合类的特点:存储空间可变的集合类
集合的结构分布图:
Collection——单列集合
Collection集合概述:
是单列集合的顶层父类接口,下面有List和Set接口
Collection集合常用方法
- add()
- remove()
- clear()
- contain()
- isEmpty()
- size()
Collection集合的遍历
Iterator:迭代器,集合专用遍历方式
Collection<String> c = new ArrayList<>(List.of("h", "e", "l", "l", "o"));
//获取迭代器对象
Iterator<String> iterator = c.iterator();
//判断迭代器中有没有下个元素
while (iterator.hasNext()) {
String s = iterator.next();
System.out.println(s);
}
//之前的for循环遍历集合
for (int i = 0; i < c.size(); i++) {
System.out.print(((ArrayList<String>) c).get(i));
}
}
迭代用户自定义类:
public class Demo {
public static void main(String[] args) {
Collection<Student> s = new ArrayList<>(List.of(new Student("小明",1),new Student("小红",2)));
Iterator<Student> it = s.iterator();
while(it.hasNext()){
Student next = it.next();
System.out.println(next.toString());
}
}
}
迭代器注意事项:
1.迭代器对象谁用谁创建
2.hasNext()和next()一定要配套使用
3.迭代器使用完毕后,指针不会复位,如果需要遍历第二次,只能重新创建迭代器对象
List集合
list集合概述
- 有序集合(也称有序序列),用户可以精准控制列表中每个元素的插入位置。也可以通过整数索引来访问元素。
- 和Set集合不同,列表通常允许重复的元素
List集合特点
- 有索引
- 可以存取重复元素
- 元素存取有序
List集合的特有方法
- add(index,element)
- remove(index,element)
- set(index,element)
- get(index)
List集合常用子类:ArrayList,LinkedList
- Arraylist:底层数据结构是数组,查询快增删慢
- LinkedList:底层数据结构是双向链表结构,查询慢增删快
- Vector:底层是数组结构,但是增删查询都慢,逐渐被替代
ConcurrentModificationException并发修改异常
List<String> list = new ArrayList<>();
list.add("hello");
list.add("world");
list.add("java");
//遍历集合,得到每一个元素,看有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
String s = iterator.next();
if(s.equals("world")) {
list.add("javaee");
}
}
总结:
- 并发修改异常产生的原因:在用迭代器遍历集合的过程中,使用了集合的方法对集合的长度进行了修改。
开始:创建迭代器对象的时候——list.iterator()的时候。
停止:while循环结束的时候。
在这之间不允许用集合的方法对集合进行添加,删除操作也就是不能修改集合长度。但set()、get()方法可以。 - 解决:如果在迭代器遍历集合的时候,想要添加元素使用ListIterator(列表迭代器)。
ListIterator列表迭代器
- 通过List集合的listIterator()方法得到,是List集合特有的迭代器
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("H");
list.add("e");
list.add("l");
list.add("l");
list.add("o");
list.add("o");
ListIterator<String> lit = list.listIterator();
/*正反向遍历
while(lit.hasNext()){
System.out.println(lit.next());
}
while(lit.hasPrevious()){
System.out.println(lit.previous());
}*/
while (lit.hasNext()) {
String s = lit.next();
//删除所有为”i"的元素
if (s.equals("l")){
lit.remove();
}
//ListIterator中特有的方法可以在遍历时添加元素
if (s.equals("e")) {
lit.add("H");
}
}
System.out.println(list);
}
迭代方法总结:
- 普通for:操作索引
- Iterator:删除元素
- ListIterator:增加元素
- 增强for:仅仅遍历
LinkedList集合
LinkedList特有功能
- addFirst(E e);列表开头添加元素
- addLast(E e);结尾添加
- getFirst();得到列表始元素
- getLast();删除最后元素
- removeFirst();删除第一个元素并返回
- removeLast();删除最后一个元素并返回
数据结构概述
常见的数据结构之栈:
- 先进后出
常见数据结构之队列:
- 先进先出
常见数据结构之数组
- 特点:查询快,增删慢
- 数组在内存中是一片连续的空间,且长度不能发生改变(事先定义好),如果空间已满,需要创建一个新的数组将老数组拷贝进来,并增加新的元素
- 数组删除元素方式:
1.创建一个新的数组,把老数组中不需要删除的元素拷贝进去
2.老数组中把要删除的元素置为Null,然后把后面的数组往前面移动,此时Null就是老数组中的最后一个元素。以后使用时就会忽略最后一个索引。
System.arraycopy(src,srcpos,des,despos,length)
第一个参数:想要拷贝的数组
第二个参数:从这个数组的第几个索引开始拷贝
第三个参数:数据的目的地
第四个参数:想要拷贝到的数组
第五个参数:要拷贝的长度
常见数据结构之链表
- 特点:增删快,查询慢
- 分类:单向链表、双向链表
- 概念:链表在内存中是不连续的,随机储存在内存中。由一个个节点组成。节点是一个个的node对象,所以是new出来的节点。链表是通过一个个节点相互链接起来的。
哈希值
- 概念:JDK根据对象的地址或者字符或者数字算出来的int类型的数值
- 如果没有重写hashcode()方法,在Object类中有一个方法可以获取对象的哈希值;pubic int hashCode();返回对象的哈希值。默认情况下不同对象的哈希值是不同的。通过重写hashCode()可以使不同对象的hash值一样。
- 如果重写了hashCode()方法那么,hash值的计算就是根据对象的属性值来计算的,就是如果重写后只要对象属性值一样他们的hashcode值也是一样
什么是哈希表?
哈希表:1.7以前 数组+链表
原理解析:
Set集合
Set特点及概述
- 无序:存取顺序不一致(说的是存入和取出的顺序不一致,而不是每次打印的顺序都要不一致)
- 不可重复
- 无索引
Set接口的常用实现类:
- HashSet:去重,存取无序,不可重复,底层实现:hash表(数组和链表)
- LinkedHashSet:去重,存取有序,效率较HashSet低些,不可重复;
- TreeSet:排序,去重;内外部比较器。底层实现:二叉树
HashSet
注意:
如果向HashSet集合中存入自定义对象,在自定义类中一定要重写hashcode和equals方法,为了保证hashset中元素不重复。
原理:
检查待存对象hashCode值是否与集合中已有元素对象hashCode值相同,如果hashCode不同则表示不同对象, 如果hashCode相同再调用equals方法进一步检查判断属性是否相同,equals返回真表示重复,否则表示不重复。
为什么要重写呢?
- 重写hashcode()用于获取元素在哈希表中的存取位置。
- 重写equals()方法用于在俩个元素的位置相同的时候比较俩个元素是否相等
存储元素的过程:
往hashset集合中存的元素一定是重写了hashcode和equals方法。
先调用hashcode()方法比较待存对象和集合中已有对象,如没有相同的hash值则直接存入;如有相同值再调用equals()方法判断对象的属性值是否一样,如果一样则为同一对象不存入,如果不一样存入hashset集合中。
LinkedHashSet
特点:
- 由哈希表和链表实现的set接口
- 存取有序
- 元素不重复
TreeSet
特点:
- 元素有序:顺序不是指存取的顺序,而是按照一定规则进行排序,具体取决于构造方法
1.TreeSet();自然排序
2.TreeSet(Comparator comparator);根据比较器定义的规则排序 - 没索引,不能重复
自然排序Comparable的使用
FFFF,t_70)说明:
假设我们通过 x.compareTo(y) 来“比较x和y的大小”。若返回“负数”,意味着“x比y小”;返回“零”,意味着“x等于y”;返回“正数”,意味着“x大于y”。
自定义排序规则Comparator接口的实现
泛型
概述:
好处:
- 把运行时期的问题提前到了编译时期
- 避免了强制类型转换
泛型类:
泛型方法
泛型接口
类型通配符
示例:
可变参数
格式:
示例:
可变参数的使用:
示例:
Map集合
map集合概述:
Map集合中的基本功能:
Map集合获取值的方法:
示例:
Map集合的遍历
示例:
一个key对应一个value,一个value可以有多个key对应。当一个key指向多个value时,原先的value就会被新的覆盖,而这种机制是由HashMap中的hash表来实现的
Collections集合工具类
例: