目录
一、对象数组的概述和使用
需求:现在有五个学生对象,将五个学生信息存储进数组中,并输出信息,
public class Collection {
public static void main(String []args){
Student []stu=new Student[5];//创建引用数据类型数组
stu[0]=new Student("学生1",18);
stu[1]=new Student("学生2",19);
stu[2]=new Student("学生3",20);
stu[3]=new Student("学生4",21);
stu[4]=new Student("学生5",22);
for(int i=0;i<stu.length;i++){
System.out.println(stu[i]);
}
}
}
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 int getAge(){
return age;
}
public void setName(String name){
this.name=name;
}
public void setAge(int age){
this.age=age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
二、集合概述和继承体系
2.1集合概述
数组的长度是固定的,当添加的元素超过了数组的长度时需要对数组进行重新定义,
所以在对数组进行初始化的时候大小设置就非常重要,但是这种方法还是太麻烦了,
java内部给我们提供了集合类,能存储任意对象,长度是可以改变的,
一般的数组和结合主要有以下几点区别:
- 数组可以存储基本数据类型,也可以存储引用数据类型
- 集合只能存储引用数据类型
- 数组的长度是固定的,不能自动增加
- 集合的长度是可变的,可以随着元素的增加而增加
如果元素的个数是固定的时候,我们用的是数组,如果元素的个数是改变的时候,我们用的是集合,
2.2集合的继承体系
三、Collection集合的基本功能
Collection是一个接口,是不能被实例化的,里面的方法都被继承他的类实现了,
下面这些方法是常用的一些基本功能,
boolean add(Object e)//在集合中加入任意对象,如果添加失败则会返回false(比如Set中不允许存储的元素重复)
boolean remove(Object o)//删除集合中的指定对象o
void clear()//清空集合中的所有对象
boolean contains(Object o)//判断集合中是否包含对象o
boolean isEmpty()//判断集合是否为空
int size()//返回集合存储元素的个数
四、集合的遍历
这里我们使用Collection接口中的toArray方法,将集合转换为Object数组,然后打印元素即可,
Collection c=new ArrayList();
c.add("a");
c.add(true);
c.add(100);
c.add(new Student("test",20));
Object arr[]=c.toArray();//将集合转换为数组
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
五、Collection集合的All功能
boolean addAll(Collection c)//将c集合中的所有元素都添加到此集合中
boolean removeAll(Collection c)//在此集合中删除c集合中的所有元素,删除的为两个集合的交集,交集为空时返回false
boolean containsAll(Collection c)//判断是否包含c集合中的所有元素
boolean retainAll(Collection c)//取本集合和c集合的交集,无交集则为空集合,本集合若没有发生改变则返回false
六、集合的迭代器遍历
集合是用来存储元素的,存储的元素需要查看,那么就需要迭代遍历来访问元素,
迭代器是通过Collection的iterator方法返回一个迭代器,而迭代器对象主要有两个方法,
boolean hasNext()//判断迭代器中是否还有元素
Object next()//返回迭代器中的第一个元素,并将指针后移
下面我们来看看具体怎么使用,
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionTest {
public static void main(String[] args){
Collection c=new ArrayList();
c.add("a");
c.add(100);
c.add(true);
c.add(new Student("测试",20));
//对集合中的元素进行迭代遍历
Iterator it=c.iterator();
while(it.hasNext()){
Object obj=it.next();
System.out.println(obj);
}
}
}
七、迭代器原理及源码解析
7.1迭代器原理
迭代器是对集合进行遍历,而每一个集合内部的存储结构都是不同的,所以每一个集合存和取都是不一样的,
那么就需要在每一个类中定义hasNext()方法和next()方法,这么做是可以的,但是会让整个集合体系过于臃肿,
迭代器则是将这两个方法像行抽取出接口,然后在每个类的内部,定义自己迭代方式,
这样做规定了整个集合体系的遍历方式都是hasNext()和nex()方法,而且代码有底层实现,使用者无需关心。
7.2迭代器源码解析
我们在ArrayList类中查找iterator方法,发现返回的是Itr对象,
原来Itr类是Iterator类的子类,它继承了Iterator类,并实现了它的hasNext()和next()方法,
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
Itr() {}
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
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];
}
八、List接口
8.1List集合特有功能
List也是一个接口,继承的是Collection,这里我们简单介绍一下List特有的一些方法,
void add(int index,E element)//在指定位置index添加元素element
E romove(int index)//删除指定位置元素,并返回该元素
E get(int index)//获取指定位置的元素,并返回该元素
E set(int index)//设置指定位置元素的值,并返回该元素
8.2List集合存储对象并遍历
List list=new ArrayList();
list.add(new Student("测试1",20));
list.add(new Student("测试2",21));
list.add(new Student("测试3",22));
list.add(new Student("测试4",23));
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
8.3并发修改异常
假设现在有一个集合,我们想判断一下里面有没有"world"元素,如果有就添加一个"java"元素,
List list=new ArrayList();
list.add("a");
list.add("world");
list.add("b");
list.add("c");
Iterator it=list.iterator();
while(it.hasNext()){
String str=(String)it.next();
if("world".equals(str)){
list.add("java");
}
}
System.out.println(list);
程序很容易编写,但是运行的时候报错了,
这个ConcurrentModificationException就是并发修改异常,
当方法检测到对象的并发修改,但不允许此种修改时,就会抛出此异常,
原来我们在生成迭代器对象的时候已经告诉迭代器我们有四个元素了,
结果在迭代遍历过程中我们又向列表中添加了一个元素,这就把迭代器整懵了,所以就抛出了并发修改异常,
解决方法就是不直接对list对象操作,对listIterator迭代器操作,使用listIterator中的add方法添加元素,
List list=new ArrayList();
list.add("a");
list.add("world");
list.add("b");
list.add("c");
ListIterator lit=list.listIterator();
while(lit.hasNext()){
String str=(String)lit.next();
if("world".equals(str)){
lit.add("java");
}
}
System.out.println(list);
可以看到程序已经不报错正常输出结果了。
九、Vector类
Vector类可以实现增长的对象数组,和数组一样,可以使用整数索引进行访问,
Vector类有一些特有的功能,
void addElement(E obj)//添加元素obj到向量中
Enumeration elements()//返回此向量的组件枚举
E elementAt(int index)//返回指定索引处的元素
在获得枚举Enumeration类中主要有两个成员方法,
boolean hasMoreElements()//判断向量中是否还有元素
E nextElement()//返回下一个元素,并指针后移
十、数组和链表
- 数组
- 查询快修改快
- 增删慢
- 链表
- 查询慢修改慢
- 增删快
在List中,ArrayList和Vector都是数组实现的,而LinkedList底层是由链表实现的,
它们具有如下特点,
- ArrayList
- 底层数据结构为数组,查询快,增删慢
- 线程不安全,效率高
- Vector
- 底层数据结构为数组,查询快,增删慢
- 线程安全,效率低
- LinkedList
- 底层数据结构为链表,查询慢,增删快
- 线程不安全,效率高