1 增强for循环
增强for循环是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
格式:
for(元素的数据类型 变量 : Collection集合or数组){ }
注意:新for循环必须有被遍历的目标。目标只能是Collection或者是数组。
建议:遍历数组时,如果仅为遍历,可以使用增强for如果要对数组的元素进行 操作,使用老式for循环可以通过角标操作。
2 泛型
2.1 泛型的引入
使用集合时,必须明确集合中元素的类型。这种方式称为:泛型。
2.2 泛型的定义与使用
我们在集合中会大量使用到泛型,这里来完整地学习泛型知识。
泛型,用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递。
2.21 含有泛型的类
定义格式:修饰符 class 类名<代表泛型的变量> { }
class ArrayList<E>{ public boolean add(E e){ } public E get(int index){ } }
使用格式:创建对象时,确定泛型的类型
例如,ArrayList<String> list = new ArrayList<String>();
此时,变量E的值就是String类型
class ArrayList<String>{ public boolean add(String e){ } public String get(int index){ } }
2.22 含有泛型的接口
定义格式:修饰符 interface接口名<代表泛型的变量> { }
例如,API中的Iterator迭代器接口
例如,API中的Iterator迭代器接口 public interface Iterator<E> { public abstract E next(); }
1、定义类时确定泛型的类型
例如
例如 public final class Scanner implements Iterator<String> { public String next(){ } }
2、始终不确定泛型的类型,直到创建对象时,确定泛型的类型
2.3 使用泛型的好处
将运行时期的ClassCastException,转移到了编译时期变成了编译失败。
避免了类型强转的麻烦。
2.4 泛型通配符
泛型是在限定数据类型,当在集合或者其他地方使用到泛型后,那么这时一旦明确泛型的数据类型,那么在使用的时候只能给其传递和数据类型匹配的类型,否则就会报错。
上述定义的printCollection方法中,由于定义的是打印集合的功能,应该是可以打印任意集合中元素的。但定义方法时,根本无法确定具体集合中的元素类型是什么。为了解决这个"无法确定具体集合中的元素类型"问题,java中,为我们提供了泛型的通配符<?>。
当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。
2.5 泛型限定
限定泛型的上限
格式:? extends E
? 代表接收E类型或者E的子类型的元素
限定泛型的下限
格式:? super E
? 代表接收E类型或者E的父类型的元素
3 List接口
3.1 List接口介绍
它是一个元素存取有序的集合
它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素
有下标
3.2 List接口中常用的方法
add(Object e):向集合末尾处,添加指定的元素
add(int index, Object e):向集合指定索引处,添加指定的元素,原有元素依次后移
remove(Object e):将指定元素对象,从集合中删除,返回值为被删除的元素
remove(int index):将指定索引处的元素,从集合中删除,返回值为被删除的元素
set(int index, Object e):将指定索引处的元素,替换成指定的元素,返回值为替
get(int index):获取指定索引处的元素,并返回该元素
由于List集合拥有索引,因此List集合迭代方式除了使用迭代器之外,还可以使用索引进行迭代。
3.21 Iterator的并发修改异常
在迭代过程中,使用了集合的方法对元素进行操作。导致迭代器并不知道集合中的变化,容易引发数据的不确定性。
并发修改异常解决办法:在迭代时,不要使用集合的方法操作元素。
那么想要在迭代时对元素操作咋办?通过ListIterator迭代器操作元素是可以的,ListIterator的出现,解决了使用Iterator迭代过程中可能会发生的错误情况。
3.3 List集合存储数据的结构
1 堆栈,采用该结构的集合,对元素的存取有如下的特点:
先进后出
栈的入口、出口的都是栈的顶端位置
压栈:就是存元素。即,把元素存储到栈的顶端位置,栈中已有元素依次向栈底方向移动一个位置。
弹栈:就是取元素。即,把栈的顶端位置元素取出,栈中已有元素依次向栈顶方向移动一个位置。
2 队列,采用该结构的集合,对元素的存取有如下的特点:
先进先出
队列的入口、出口各占一侧
3 数组,采用该结构的集合,对元素的存取有如下的特点:
查找元素快:通过索引,可以快速访问指定位置的元素
增删元素慢
4 链表,采用该结构的集合,对元素的存取有如下的特点:
多个节点之间,通过地址进行连接
查找元素慢
增删元素快
3.4ArrayList集合
ArrayList集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList是最常用的集合。
许多程序员开发时非常随意地使用ArrayList完成任何需求,并不严谨,这种用法是不提倡的。
3.5 LinkedList集合
LinkedList集合数据存储的结构是链表结构。方便元素添加、删除的集合。
LinkedList集合数据存储的结构是链表结构。方便元素添加、删除的集合。
addFirst(E e)将指定元素插入该列表的开头
addLast(E e)将指定元素添加到刺裂表的末尾
getFirst()返回刺裂表的第一个元素
getLst()返回此列表的最后一个元素
removeFirst()移除并返回此列表的第一个元素
removeLast()移除并返回此列表的最后一个元素
pop()从此列表所表示的堆栈处弹出一个元素 和removeFirst 效果相同
push()将元素推入此列表所表示的堆栈 和 addLast效果相同
isEmpty()如果列表不包含元素则返回true
LinkedList是List的子类,List中的方法LinkedList都是可以使用
3.6 Vector集合
Vector集合数据存储的结构是数组结构,为JDK中最早提供的集合。Vector中提供了一个独特的取出方式,就是枚举Enumeration,它其实就是早期的迭代器。此接口Enumeration的功能与 Iterator 接口的功能是类似的。Vector集合已被ArrayList替代。枚举Enumeration已被迭代器Iterator替代。
l Vector常见的方法:
addElement()将指定的组件添加到此向量的末尾使其大小增加1
elementAt()返回指定所引出的组件
elements 返回词向量的组件的枚举
Enumeration常见方法
hasMoreElements()测试此枚举是否包含更多的元素
nextElement()如果此枚举至少还有一个可以提供的元素则返回此枚举的下一个元素
4 Set接口
4.1 Set接口介绍
不能有重复元素 无序 没有索引
4.2 HashSet集合介绍
查阅HashSet集合的API介绍:此类实现Set接口,由哈希表支持(实际上是一个 HashMap集合)。HashSet集合不能保证的迭代顺序与元素存储顺序相同。
HashSet集合,采用哈希表结构存储数据,保证元素唯一性的方式依赖于:hashCode()与equals()方法。
4.3 HashSet存储JavaAPI中的类型元素
给HashSet中存储JavaAPI中提供的类型元素时,不需要重写元素的hashCode和equals方法,因为这两个方法,在JavaAPI的每个类中已经重写完毕,如String类、Integer类等。
4.4 HashSet存储自定义类型元素
给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一