JavaSE 集合进阶
1. Collection
1.1 集合知识回顾
集合类的特点:
提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变
1.2 集合类体系结构
1.3 Collection 集合概述和使用
Collection 集合概述:
- 是单列集合的顶层接口,它表示一组对象,这些对象也被称为Collection 的元素
- JDK 不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现
创建Collection 集合的对象
- 多态的方式
- 具体的实现类ArrayList
package com.Collection;
import java.util.ArrayList;
import java.util.Collection;
public class Demo01 {
public static void main(String[] args){
//创建Collection集合对象
Collection<String> c = new ArrayList<String>();
//添加元素:boolean add(E e)
c.add("cappuccino");
c.add("love");
c.add("bug");
System.out.println(c);
}
}
1.4 Collection 集合常用方法
1.5 Collection 集合的遍历
Iterator:迭代器,集合的专用遍历方式
- Iterator <E> iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
- 迭代器是通过集合的iterator()方法得到的,所以我们说它是依赖于集合而存在的
Iterator中的常用方法:
- E next():返回迭代中的下一个元素
- boolean hasNext():如果迭代具有更多元素,则返回true
package com.Collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Demo02 {
public static void main(String[] args){
//创建Collection集合对象
Collection<String> c = new ArrayList<String>();
//添加元素:boolean add(E e)
c.add("cappuccino");
c.add("love");
c.add("bug");
/*
Iterator <E> iterator():返回次集合中元素的迭代器,
通过集合的iterator()方法得到
*/
Iterator<String> it = c.iterator();
/*boolean hasNext():如果迭代具有更多元素,则返回true
E next():返回迭代中的下一个元素
*/
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
}
}
1.6 案例
-
需求:
创建一个存储学生对象的集合,存储三个学生对象,使用程序实现在控制台遍历该集合 -
思路:
- 定义学生类
- 创建Collection集合对象
- 创建学生对象
- 把学生添加到集合
- 遍历集合(迭代器方式)
package com.Collection;
public class Student {
private String name;
private int age;
public Student(){
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.Collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
需求:
创建一个存储学生对象的集合,存储三个学生对象,使用程序实现在控制台遍历该集合
思路:
1.定义学生类
2.创建Collection集合对象
3.创建学生对象
4.把学生添加到集合
5.遍历集合(迭代器方式)
*/
public class CollectionTest {
public static void main(String[] args){
//创建Collection集合对象
Collection<Student> c = new ArrayList<Student>();
//创建学生对象
Student s1 = new Student("苦瓜",21);
Student s2 = new Student("半仙儿",22);
Student s3 = new Student("研",23);
//把学生添加到集合
c.add(s1);
c.add(s2);
c.add(s3);
//遍历集合(迭代器方式)
Iterator<Student> it = c.iterator();
while(it.hasNext()){
Student s = it.next();
System.out.println(s.getName() + "," + s.getAge());
}
}
}
2. List
2.1 List 集合概述和特点
-
List 集合概述
- 有序集合(也成为了序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引访问元素,并搜索列表中的元素
- 与 set 集合不同,列表通常允许重复的元素
-
List 集合的特点
- 有序:存储和取出元素顺序一致
- 可重复:存储的元素可以重复
package com.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*
List 集合的特点:
有序:存储和取出元素顺序一致
可重复:存储的元素可以重复
*/
public class Demo01 {
public static void main(String[] args){
//创建集合对象
List<String> list = new ArrayList<String>();
//添加元素
list.add("研");
list.add("半仙儿");
list.add("苦瓜");
list.add("研");
//输出集合
System.out.println(list);
//采用迭代器的方式遍历
Iterator<String> it = list.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
}
}
2.2 List 集合特有的方法
2.3 并发修改异常
- 并发修改异常:ConcurrentModificationException
- 产生原因:
迭代器遍历的过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中预期修改值和实际修改值不一致 - 解决方案:
用for循环遍历,然后用集合对象做相应的操作即可
package com.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*
需求:
集合里面有三个元素,遍历集合,得到每一个元素,看有没有"研"这个元素;
如果有,就添加一个"粉色匡威"元素
ConcurrentModificationException:并发修改异常
当不允许这样的修改时,可以通过检测到对象的并发修改的方法来抛出此异常
*/
public class ConcurrentModificationException {
public static void main(String[] args){
List<String> list = new ArrayList<String>();
list.add("苦瓜");
list.add("半仙儿");
list.add("研");
Iterator<String> it = list.iterator();
while(it.hasNext()){
String s = it.next();
if(s.equals("研")){
list.add("粉色匡威");
}
}
// for(int i=0;i<list.size();i++){
// String s = list.get(i);
// if(s.equals("研")){
// list.add("粉色匡威");
// }
// }
System.out.println(list);
}
}
/*
并发修改异常的源码分析
*/
public interface List<E>{
Iterator<E> iterator();
boolean add(E e);
}
public abstract class AbstractList<E>{
protected int modCount = 0;
}
public class ArrayList<E> extends AbstractList<E> implements List<E>{
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
public boolean add(E e) {
ensureCapacityInternal(size + 1); /* Increments modCount!!
modCount++
*/
elementData[size++] = e;
return true;
}
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int expectedModCount = modCount;
/*
modCount:实际修改集合的次数
expectedModCount:预期修改集合的次数
*/
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
}
2.4 ListIterator
ListIterator: 列表迭代器
- 通过List集合的 ListIterator() 方法获得,所以说它是List集合特有的迭代器
- 允许程序员沿任意方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置
ListIterator中常用方法:
- E next():返回迭代中的下一个元素
- boolean hasNext():如果迭代具有更多元素,则返回 true
- E previous():返回列表中的上一个元素
- boolean hasPrevious():如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回 true
- void add(E e):将指定的元素插入列表
package com.ListIterator;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
/*
ListIterator: 列表迭代器
通过List集合的 listIterator() 方法获得,所以说它是List集合特有的迭代器
允许程序员沿任意方向遍历列表的列表迭代器,在迭代期间修改列表,
并获取列表中迭代器的当前位置
ListIterator中常用方法:
E next():返回迭代中的下一个元素
boolean hasNext():如果迭代具有更多元素,则返回 true
E previous():返回列表中的上一个元素
boolean hasPrevious():如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回 true
void add(E e):将指定的元素插入列表
*/
public class Demo01 {
public static void main(String[] args){
//创建集合对象
List<String> list = new ArrayList<String>();
//添加元素
list.add("苦瓜");
list.add("粉色");
list.add("匡威");
//通过List集合的 listIterator() 方法获得
// ListIterator<String> lit = list.listIterator();
// while(lit.hasNext()){
// String s = lit.next();
// System.out.println(s);
// }
// System.out.println("--------");
// //逆向遍历(很少用)
// while(lit.hasPrevious()){
// String s = lit.previous();
// System.out.println(s);
// }
ListIterator<String> lit = list.listIterator();
while(lit.hasNext()){
String s = lit.next();
if(s.equals("苦瓜")){
lit.add("研");
}
}
System.out.println(list);
}
}
/*
ListIterator源码分析
*/
public interface List<E>{
Iterator<E> iterator();
ListIterator<E> listIterator();
}
public abstract class AbstractList<E>{
protected int modCount = 0;
}
public class ArrayList<E> extends AbstractList<E> implements List<E>{
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
...
}
public ListIterator<E> listIterator() {
return new ListItr(0);
}
private class ListItr extends Itr implements ListIterator<E> {
public void add(E e) {
checkForComodification();
try {
int i = cursor;
ArrayList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount; //重点
/*
列表迭代器的add()方法在添加元素
之后会将实际修改次数赋值给预期修
改次数,所有不会出现并发修改异常
*/
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
}
2.5 增强 for 循环
增强for循环:简化数组和 Collection 集合的遍历
- 实现 Iterable 接口的类允许其对象成为增强型 for 语句的目标
- 它是 JDK5 之后出现的,其内部原理是一个 Iterator 迭代器
增强 for 的格式
- 格式:
for(元素数据类型 变量名:数组或者Collection集合){
//在此处使用变量即可,该变量就是数组或者集合的元素
} - 范例:
int[] arr = {
1,2,3};
for(int i:arr){
System.out.println(i);
}
package com