iterator(迭代器)
迭代器是一种机制,一种用于遍历集合的接口
Iterator不是一个集合,而是一种用于访问集合的方法
Iterator 是 Java 迭代器最简单的实现,ListIterator 是 Collection API 中的接口, 它扩展了 Iterator 接口
最常用的三个方法:
- next()-用于返回下一个元素,并将迭代器的指针移到下一个位置
- hasNext()-用于判断集合是否还有下一个元素可以访问
- remove()-从集合中删除迭代器最后访问的元素
使用方法
// 引入 ArrayList 和 Iterator 类
import java.util.ArrayList;
import java.util.Iterator;
public class RunoobTest {
public static void main(String[] args) {
// 创建集合
ArrayList<String> sites = new ArrayList<String>();
sites.add("Google");
sites.add("Runoob");
sites.add("Taobao");
sites.add("Zhihu");
// 获取迭代器
Iterator<String> it = sites.iterator();
// 输出集合中的第一个元素
System.out.println(it.next());//Google
}
}
[!note]
Java 迭代器是一种单向遍历机制,即只能从前往后遍历集合中的元素,不能往回遍历。同时,在使用迭代器遍历集合时,不能直接修改集合中的元素,而是需要使用迭代器的 remove() 方法来删除当前元素
泛型
需求:写一个排序方法,能够对整型数组、字符串数组甚至其他类型数组进行排序,如何实现?使用泛型
泛型符号 | 代表意义 |
---|---|
E | Element(在集合中使用,代表元素) |
T | Type(Java类) |
K | Key(键) |
V | Value(值) |
N | Number(数值类型) |
? | 不确定的java类型 |
设置泛型可以有多个比如: <K, V>
泛型限定
泛型表示 | 代表含义 |
---|---|
<?> | 任意类型 |
<? extends A> | 代表只能是A类型或者是A的子类类型 |
<? super A> | 代表只能是A类型或者是A的父类类型 |
泛型的使用:需求:设置一个管理系统的接口
//分析:针对对象的增删改查
public interface ManageSystem<T>{
public int add(T t);
public int remove(T t);
...
}
学生管理系统
public class StudentManageSystem implements ManageSystem<Student>{
@Override
public int add(Student stu){
return 0;
}
@Override
public int remove(Student stu){
return 0;
}
...
}
用户管理系统
public class UserManageSystem implements ManageSystem<User>{
@Override
public int add(User user){
return 0;
}
@Override
public int remove(User user){
return 0;
}
...
}
ArrayList
ArrayList
类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。
ArrayList
继承了 AbstractList
,并实现了 List
接口。
[!note]
应用场景:
- 频繁访问列表中的某一个元素
- 只需要在列表末尾进行添加或删除元素操作
ArrayList
的使用
import java.util.ArrayList;
ArrayList<E> objectName = new ArrayList<>();
添加元素
ArrayList<String> list = new ArrayList<>();
//直接添加
list.add("xxx");
list.add("yyy");
//指定下标添加
list.add(1, "zzz");
查询元素
//根据下标查询,下标从0开始
System.out.println(list.get(1));
修改
list.set(1, "aaa");
删除
//指定下标修改,下标从0开始
list.remove(1);
//直接删除元素:如果该元素不存在则返回空值
list.remove("aaa");
遍历
//方式一:for循环
for (int i = 0; i < arr1.size(); i++) {
System.out.println(arr1.get(i));
}
//方式二:for-each循环
for(String element: list){
System.out.print(element)
}
//方式三:迭代器(推荐)
ListIterator<String> itr = list.listIterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
追加
ArrayList<String> newList1 = new ArrayList<>();
Collections.addAll(newList1, "aaa","bbb","ccc","ccc");//使用Collections.addAll装载对象
list.addAll(newList1);//addAll(没有指定下标index,默认添加到末尾)
ArrayList<String> newList1 = new ArrayList<>();
Collections.addAll(newList1, "aaa","bbb","ccc","ccc");//使用Collections.addAll装载对象
list.addAll(1, newList1);//addAll(指定下标index,则从指定位置插入)
元素操作
//清空集合
list.clear();
//判断集合中是否存在指定元素:存在则返回true,否则返回false
list.contains("aaa");
//判断集合中第一次出现该元素的下标,存在则返回下标,不存在则返回-1
list.indexOf("aaa");
//判断一个集合是否包含另一个集合,包含则返回true,不包含则返回false
list.containsAll(list2);
//判断集合是否为空,为空则返回true,不为空则返回false
list.isEmpty();
//将一个集合中包含另一个集合的元素删除(删除交集)
list.removeAll(list2);
//将一个集合中包含另一个集合的元素保留(保留交集)
list.retainAll(list2);
类型转化
//将集合转化为数组
Object[] objs = list.toArray();
System.out.println(Arrays.toSting(objs));
//将集合转化为指定类型的数组
String[] strs = new String[list.size()];
list.toArray(strs);
System.out.println(Arrays.toString(strs));
LinkedList
LinkedList
(链表),是一种常见的数据结构,是一种线性表,但不会按照现行顺序存储数据,而是在每一个节点里存储下一个节点的地址
链表可分为单向链表和双向链表。
单向链表:当前节点的值和下一节点的地址
双向链表:前一个节点的地址,当前节点的值,下一节点的地址
[!note]
与 ArrayList 相比,LinkedList 的增加和删除的操作效率更高,而查找和修改的操作效率较低。
应用场景:
- 通过循环迭代来访问列表中的某些元素
- 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作
LinkedList的使用
import java.util.LinkedList;
LinkedList<E> objectName = new LinkedList<>();//普通创建方法
LinkedList<E> objectName = new LinkedList(Collection<? extends E> c);//使用集合创建链表
添加元素
LinkedList<String> list = new LinkedList<>();
//直接添加
list.add("xxx");
list.add("yyy");
//指定下标添加
list.add(1, "zzz");
查询元素
//根据下标查询,下标从0开始
System.out.println(list.get(1));
修改
list.set(1, "aaa");
删除
//指定下标修改,下标从0开始
list.remove(1);
//直接删除元素:如果该元素不存在则返回空值
list.remove("aaa");
//删除第一个元素
list.poll();
list.pollForst();
list.removeFirst();
//删除最后一个元素
list.pollLast();
list.removeLast();
遍历
//方式一:for循环
for (int i = 0; i < arr1.size(); i++) {
System.out.println(arr1.get(i));
}
//方式二:for-each循环
for(String element: list){
System.out.print(element)
}
//方式三:迭代器(推荐)
ListIterator<String> itr = list.listIterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
//方式四:ListIterator
ListIterator<String> itr = list.listIterator();
while(itr.hasNext()){
System.out.println(itr.next())
}
//凡是五:指定开始下标遍历
ListIterator<String> itr = list.iterator(1);
while(itr.hasNext()){
String element = itr.next();
System.out.println(element);
}
//方式六:倒序遍历
ListIterator<String> itr = list.iterator(list.size());
while(itr.hasPrevious()){
String element = itr.previous();
System.out.println(element);
}
追加
LinkedList<String> newList1 = new LinkedList<>();
Collections.addAll(newList1, "aaa","bbb","ccc","ccc");//使用Collections.addAll装载对象
list.addAll(newList1);//addAll(没有指定下标index,默认添加到末尾)
LinkedList<String> newList1 = new LinkedList<>();
Collections.addAll(newList1, "aaa","bbb","ccc","ccc");//使用Collections.addAll装载对象
list.addAll(1, newList1);//addAll(指定下标index,则从指定位置插入)
元素操作
//清空集合
list.clear();
//判断集合中是否存在指定元素:存在则返回true,否则返回false
list.contains("aaa");
//判断集合中第一次出现该元素的下标,存在则返回下标,不存在则返回-1
list.indexOf("aaa");
//判断一个集合是否包含另一个集合,包含则返回true,不包含则返回false
list.containsAll(list2);
//判断集合是否为空,为空则返回true,不为空则返回false
list.isEmpty();
//将一个集合中包含另一个集合的元素删除(删除交集)
list.removeAll(list2);
//将一个集合中包含另一个集合的元素保留(保留交集)
list.retainAll(list2);
类型转化
//将集合转化为数组
Object[] objs = list.toArray();
System.out.println(Arrays.toSting(objs));
//将集合转化为指定类型的数组
String[] strs = new String[list.size()];
list.toArray(strs);
System.out.println(Arrays.toString(strs));
LinkedList队列模式(先进先出)
while(!list.isEmpty()){
String element = list.removeFirst();
System.out.println(element);
}
LinkedList栈模式(先进后出)
while(!list.isEmpty()){
String element = list.removeLast();
System.out.println(element);
}
[!note]
Iterator
和ListIterator
的区别
Iterator
:Cllection
接口下所有的实现类都可以获取的选代器,可以在遍历时删除元素
Listlterator
:List
接口下所有的实现类可以获取的迭代器,可以在遍历时删除、替换、添加元素,也可以指定下标开始遍历,还可以倒叙遍历
Vector及Stack
Vector
从JDK1.0开始,JDK1.2开始有集合框架的概念,为保留Vector
,让其实现了List
接口
Vector
使用与ArrayList
完全一样
Vector
传统使用
public static void main(String[] args) {
/**
* Vector理解
* 从JDK1.0开始的集合类,JDK1.2开始有了集合框架的概念
* 为了将Vector保留,让Vector实现了List接口
*/
Vector<String> vector = new Vector<>();
//添加
vector.addElement("111");
//删除
vector.removeElementAt(0);
//遍历
Enumeration<String> elements = vector.elements();
while(elements.hasMoreElements()){
System.out.println(elements.nextElement());
}
}
Stack
-栈(先进后出)
public static void main(String[] args) {
/**
* stack-栈模式
*/
Stack<String> s = new Stack<>();
//添加元素到栈顶
s.push("111");
s.push("222");
s.push("333");
//获取栈顶元素
System.out.println(s.peek());
//获取元素到栈顶的距离-从1开始数
System.out.println(s.search("111"));
//判断集合是否为空内容
while(!s.isEmpty()){
//删除栈顶元素并返回
String str = s.pop();
System.out.println(str);
}
}
HashSet及LinkedHashSet
HashSet
HashSet
集合的方法与ArrayList
方法基本相同,但是不包含下标操作
HashSet
的特点:无序且去重
HashSet<String> arr1 = new HashSet<>();
arr1.add("0001");
arr1.add("0002");
arr1.add("0003");
arr1.add("Aa");
arr1.add("BB");
for (String element : arr1) {
System.out.println(element);//Aa BB 0002 0003 0001
}
添加顺序:
- 获取元素的
hash
值–hashCode()
- 通过hash值计算元素在数组中的下标
- 判断下标上是否有元素
- 没有元素,直接添加
- 有元素,比较两个对象是否相同(
hash值&&(==||equals)
)- 相同,不添加(达到去重效果)
- 不相同,形成单向链表(JDK1.8后是尾插,JDK1.7是头插)
遍历步骤:
遍历数组(顺序遍历)
[!note]
添加步骤的处理逻辑与遍历步骤的处理逻辑不相同,所以无序
LinkedHashSet
LinkedHashSet
的特点:无序且去重
继承关系:LinkedHashSet
继承于HashSet
LinkedHashSet<String> arr1 = new LinkedHashSet<>();
arr1.add("0001");
arr1.add("0002");
arr1.add("0003");
arr1.add("Aa");
arr1.add("BB");
for (String element : arr1) {
System.out.println(element);
}
添加顺序:
- 获取元素的
hash
值–hashCode()
- 通过
hash
值计算元素在数组中的下标 - 判断下标上是否有元素
- 没有元素,直接添加,但是每个节点记录了前后节点的地址(双向链表)
- 有元素,比较两个对象是否相同(
hash值&&(==||equals)
)- 相同,不添加(达到去重效果)
- 不相同,形成单向链表(JDK1.8后是尾插,JDK1.7是头插)
遍历步骤:
与LinkedList
遍历顺序相同(按照当前节点存储的的下一节点地址查询)
TreeSet
TreeSet集合的方法与HashSet方法相同
特点:自然排序(TreeSet会根据不同的类型使用不同的排序规则)
-
TreeSet
存储String
—>字典排序 -
TreeSet
存储Integer
—>数字排序\数字升序
添加顺序:
- 获取元素的
hash
值–hashCode()
- 通过
hash
值计算元素在数组中的下标 - 判断下标上是否有元素
- 没有元素,直接添加,但是每个节点记录了前后节点的地址(双向链表)
- 有元素,比较两个对象是否相同(
hash值&&(==||equals)
)- 相同,不添加(达到去重效果)
- 不相同,形成单向链表(JDK1.8后是尾插,JDK1.7是头插)
遍历步骤:
与LinkedList
遍历顺序相同(按照当前节点存储的的下一节点地址查询)