数组对象
数组是容器,即可以存储基本数据类型也可以存储引用数据类型,存储了引用数据类型的数组成为对象数组,如:String【】、Person【】、Student【】
public static void main(String[] args) {
//创建存储Person对象的数组
Person[] person = {
new Person("张三",20),
new Person("李四",30),
new Person("王五",28),
};
//遍历数组
for (int i = 0; i <person.length ; i++) {
Person person = person[i];
System.out.println(person.getName()+"::"+person.getAge());
}
}
数组弊端:
- 数组长度是固定的,一旦创建不可修改需要
- 需要添加元素,只能创建新数组,将数组中的元素进行复制
为了解决数组的定长问题,Java语言从JDK1.2后开始出现集合框架
Collection集合
- 集合:集合是Java中提供的一种容器,可以用来存储多个数据
集合和数组都是容器,有什么区别?
- 数组的长度是固定的,集合的长度是可变的
- 数组中存储的是同一类型的元素,可以存储任意类型数据。集合存储的都是引用数据类型,如果想存储基本类型数据需要存储相应的包装类型
集合类的继承关系
Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是 java.util.List
和
java.util.Set
。其中,
List
的特点是元素有序、元素可重复。
Set 的特点是元素不可重复。
List
接口的主要实现类有
java.util.ArrayList
和
java.util.LinkedList
,
Set 接口的主要实现类有 java.util.HashSet
和
java.util.LinkedHashSet
。
注意
:
这张图只是我们常用的集合有这些,不是说就只有这些集合。
集合本身是一个工具,它存放在
java.util
包中。在
Collection
接口定义着单列集合框架中最最共性的内容。
Collection接口方法
Collection是所有单列集合的父类接口,因此Collection中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合。方法如下:
public boolean add(E e):把给定的对象添加到当前集合中 。
public boolean addAll(Collection<? extends E>)
将另一个集合元素添加到当前集合中。
public void clear()
:
清空集合中所有的元素。
public boolean remove(E e)
:
把给定的对象在当前集合中删除。
public boolean contains(Object obj)
:
判断当前集合中是否包含给定的对象。
public boolean isEmpty()
:
判断当前集合是否为空。
public int size()
:
返回集合中元素的个数。
public Object[] toArray()
:
把集合中的元素,存储到数组中。
迭代器 Iterator接口
在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口 java.util.Iterator
想要遍历Collection集合,那么就要获取该集合迭代器完成迭代操作,下面介绍一下获取迭代器的方法:public Iterator iterator() : 获取集合对应的迭代器,用来遍历集合中的元素的。
迭代
:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。
Iterator
接口的常用方法如下:
public E next()
:
返回迭代的下一个元素。
public boolean hasNext()
:
如果仍有元素可以迭代,则返回
true
。
接下来我们通过案例学习如何使用
Iterator
迭代集合中元素:
public static void main(String[] args) {
//使用多态方式创建对象
Collection<String > coll = new ArrayList<String>();
//添加元素到集合
coll.add("串串");
coll.add("脱口秀");
coll.add("汪汪队");
//遍历
//使用迭代器遍历 每个集合对象都有自己的迭代器
Iterator<String> it = coll.iterator();
//泛型指的是 迭代出元素的数据类型
while(it.hasNext()){//判断是否有迭代元素
String s = it.next();//获取迭代出的元素
System.out.println(s);
}
}
迭代器的实现原理
之前的案例完成了
Iterator
遍历集合的整个过程。当遍历集合时,首先通过调用
t
集合的
iterator()方法获得迭代器对象,然后使用
hashNext()
方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,为了让初学者能更好地理解迭代器的工作原理,接下来通过一个图例来演示
Iterator
对象迭代元素的过程:
在调用
Iterator
的
next方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next
方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用
next方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到
hasNext
方法返回
false,表示到达了集合的末尾,终止对元素的遍历。
并发修改异常
使用迭代器遍历集合中,不能使用集合本身的方法改变集合的长度,一旦被改变将会抛出ConcurrentModificationException并发修改异常。
public static void main(String[] args) {
Collection<String> coll = new ArrayList<String >();
coll.add("hello1");
coll.add("hello2");
coll.add("hello3");
coll.add("hello4");
Iterator<String> it = coll.iterator();
while(it.hasNext()){
String str = it.next();
if("hello2".equals(str)){
coll.add("hello5");
}
}
}
运行结果:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at wensong.CollectionTest.IteratorException.main(IteratorException.java:16)
Process finished with exit code 1
以上程序,在迭代器遍历过程中,使用了集合
add方法修改集合的长度,这个操作是不允许的,被禁止的,程序中会抛出并发修改异常。
注意
:如果我们使用集合的
remove()方法同样会抛出并发修改异常,但是删除倒数第二个元素则不会抛出异常。
原因:抛出并发修改异常的方法是迭代器的
next()
方法,当删除倒数第二个元素后,本次循环结束,再次执行
while循环时,此时条件为
false
,循环停止,没有再执行
next()
方法,所以没有异常抛出。