文章目录
一、集合
集合体系结构
由于存在不同的数据结构(数据的组织、存储方式),所以Java为我们提供了不同的集合,但是不同的集合它们的功能都是相似的,不断向上抽取,将共性抽取出来,,这就是集合体系结构形成的原因。
如何学习
- 从最顶层开始学习,因为最顶层包含了所有的共性。
- 从最底层开始使用,因为最底层就是具体的实现。
本次要学习的集合
Collection
List
ArrayList
二、Collection —— 是接口,不能实例化
常见成员方法
boolean add(E e)
添加元素。永远可以添加成功,因为ArrayList
允许重复void clear()
清空集合。boolean contains(Object o)
判断集合中是否含指定元素。boolean isEmpty()
判断是否为空boolean remove(Object o)
删除元素。int size()
返回集合中元素的个数Object[] toArray()
将集合转换成一个Object
类型的数组
eg:Object[] objs = c.toArray();
Iterator<E> iterator();
迭代器,之后详细讲。
迭代器 —— Iterator
集合的遍历方式
toArray();
把集合转换成数组,遍历数组即可iterator
返回一个迭代器,通过迭代器来迭代集合。
Iterator常用成员方法
E next();
返回下一个元素,若无元素可供获取,出现NoSuchElementException
boolean hasNext();
判断是否有元素可供获取
代码示例
Collection c = new ArrayList(); //创建集合对象c
c.add("hello"); //添加元素
c.add("world");
Iterator it = c.iterator(); //创建迭代器,相当于创建c的副本
while(it.hasNext()){ //判断是否有下一个元素
System.out.println(it.next()); //输出元素
}
迭代器Iterator的注意要点
迭代器是依赖于集合的,相当于集合的副本,当迭代器在操作的时候,如果发现和集合不一样,会抛出异常ConcurrentModificationException
,即并发修改异常。
如何解决呢?
- 别用迭代器。(笑…)
- 在使用迭代器进行遍历时,使用迭代器对象进行修改。
eg:在"java"后添加"android"。
错误代码示例
List c = new ArrayList();
c.add("hello");
c.add("world");
c.add("java");
ListIterator lit = c.listIterator();
while(lit.hasNext()){
String s = (String) it.next();
if(s.equals("java")){
c.add("android"); //不能直接在原集合中修改,出现并发修改异常,原集合与迭代器对象不一致
}
}
正确代码示例
List c = new ArrayList();
c.add("hello");
c.add("world");
c.add("java");
ListIterator lit = c.listIterator();
while(lit.hasNext()){
String s = (String) lit.next();
if(s.equals("java")){
lit.add("android"); //在迭代器对象中进行修改
}
}
三、泛型
使用集合存储自定义对象并遍历。由于集合可以储存任意类型的对象,当我们储存了不同类型的对象,就有可能在转换的时候出现类型转换异常。所以Java为解决这一问题,提供了一种机制,叫做泛型。
概念
泛型是一种广泛的类型,把明确数据类型的工作提前到了编译时期,借鉴了数组的特点。
好处
- 避免类型转换的问题。
- 可以减少黄色警告线
- 可以简化我们代码的书写
使用场景
API中看到<E>
,就可以使用泛型。
代码示例
Collection<Student> c = new ArrayList<Student>();
Student s1 = new Student("小李", 23);
Student s2 = new Student("小芳", 24);
c.add(s1);
c.add(s2);
Iterator<Student> it = c.iterator();
while(it.hasNext()){
Student stu = it.next();
System.out.println(stu.name);
}
四、foreach 增强for循环
增强for循环,一般用于遍历集合或数组。
格式
for(元素的类型 变量名 : 集合或者数组对象){
可以直接使用变量的代码;
}
注意
在增强for循环中不能修改集合,否则会出现并发修改异常,是因为增强for循环的底层还是迭代器。
代码示例
Collection<String> c = new ArrayList<String>();
c.add("hello");
c.add("world");
c.add("java");
for(String str : c){
System.out.println(str);
}
五、常见数据结构 — 数组
特点
- 数组的长度一旦定义,就不可改变
- 数组中的元素都有整数索引
- 数组只能储存同一类型的元素
- 数组可以储存基本数据类型,也可以储存引用数据类型
如何获取数组中第3位元素
可以通过索引,arr[2] //arr为数组对象名
在3元素后添加一个新的元素8
- 创建一个新的数组,长度是原数组长度+1
- 遍历原来的数组,并且插入到新数组当中
- 当碰到元素3时,在元素3后面添加新的元素8
- 最后把剩余的元素添加到元素8后面即可
数组总结
查找快,增删慢
六、常见数据结构 — 链表
由链子链接起来的一堆结点。
结点:地址值,值,下一个结点地址值。如图所示
如何获取结点3的值
没有好的方法,只能遍历链表,然后一个个查看。
在结点2之后添加一个新的结点值为8
- 把结点2的地址值改为新结点的地址值
- 把新结点的下一个地址值改为003。如图所示
链表总结
查询慢,增删快
七、常见数据结构 — 栈、队列
栈
先进后出,如弹夹。
队列
先进先出,如排队、火车进出洞。
八、List
特点
- 有序的(存储和读取的顺序是一致的)
- 有整数索引
- 允许重复
特有功能 —— 增删改查
void add(int index, Element)
在指定位置添加指定元素E get(int index)
根据索引返回元素E remove(int index)
删除指定元素并返回E set(int index, E element)
将指定索引位置的元素替换为指定元素,将原先元素返回
List的常用子类
ArrayList
底层是数组结构,查询快,增删慢。
LinkedList
底层是链表,查询慢,增删快。
如何使用不同的集合
- 若查询多,增删少 ——
ArrayList
- 若查询少,增删多 ——
LinkedList
- 若不知道使用什么 ——
ArrayList
LinkedList的特有功能
void addFirst(E e);
将元素添加到索引为0的位置void addLast(E e);
将元素添加到索引为size()-1的位置E getFirst();
获取索引为0的元素并返回E getLast();
获取索引为size()-1的元素并返回E removeFirst();
删除索引为0的元素并返回E removeLast();
删除索引为size()-1的元素并返回