第15天 迭代器以及ArrayList、LinkedList原理

时间:2021-03-15 19:28:32
1.迭代器
Collection 单例集合的根接口
List:如果是实现了 List接口的集合类,该集合类具备 的特点: 有序、可重复。
Set:如果是实现了Set接口的集合类,该集合具备的特点: 无序,不可 重复。
Collection---迭代的方法:
toArray()
iterator()
迭代器的作用:用于抓取集合中的元素
迭代器的方法:
hasNext()   问是否有元素可遍历。如果有元素可以遍历,返回true,否则返回false 。(当前指针是否有指向元素,如果有返回true,否则返回false)
next()    获取元素...(获取当前指针指向的元素并返回当前的元素,然后指针向下移动一个单位)
remove()  移除迭代器最后一次返回 的元素。
NoSuchElementException 没有元素的异常。 
出现的原因: 没有元素可以被迭代了。。。
public class Demo2 {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("狗娃");
c.add("狗剩");
c.add("铁蛋");
c.add("美美");
/*
* //遍历集合的元素------>方式一: 可以使用toArray方法。 Object[] arr = c.toArray(); //
* toArray() 把集合 的元素存储到一个 Object的数组中 返回。 for(int i = 0 ; i<arr.length ;
* i++){ System.out.print(arr[i]+","); }

* //要求使用iterator迭代器遍历。
*/
Iterator it = c.iterator(); // 返回一个迭代器
// 疑问:iterator()方法返回的是一个接口类型,为什么接口又可以调用方法可以使用呢?
// iterator 实际 上返回的是iterator接口的实现类对象。
/*
* while(it.hasNext()){ // hasNext() 问是否有元素可以遍历。
* System.out.println("元素:"+ it.next()); //获取元素 }
*/
/*
* it.next(); it.next(); it.remove(); //删除迭代器最后一次返回的元素。
*/
// 清空集合 的元素
while (it.hasNext()) {
it.next();
it.remove();
}
System.out.println("集合的元素:" + c);
}
}
2.作业-登录注册
使用集合实现注册登陆功能,
第一步: 提示用户选择功能, A(注册)  B(登陆) 。 要求: 功能选择 的时候要忽略大小写。
注册:
1. 提示用户输入注册的账号(数字)与密码,如果输入账号已经存在集合中,提示用户重新输入。 注册完毕之后,把集合中的所有用户信息打印出来。(使用:toArrry()方法)
登陆: 
提示用户输入登陆的账号与密码,如果账号与密码这个用户已经存在集合中,那么登陆成功,否则登陆失败。
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Scanner;
//用户
class User{
int id;  //账号
String password;  //密码
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User(int id, String password) {
this.id = id;
this.password = password;
}


@Override
public boolean equals(Object obj) {
User user = (User)obj;
return this.id==user.id;
}
@Override
public String toString() {
return "{ 账号:"+this.id+" 密码:"+this.password+"}";
}
}
public class Demo1 {
static Scanner scanner = new Scanner(System.in);
static Collection users = new ArrayList(); //使用该集合保存所有的用户信息..
public static void main(String[] args) {
while(true){
System.out.println("请选择功能      A(注册 )    B(登陆)");
String option = scanner.next();
if("a".equalsIgnoreCase(option)){
reg();
}else if("b".equalsIgnoreCase(option)){
login();
}else{
System.out.println("你的选择有误,请重新输入");
}
}
}
public static void login() {
System.out.println("请输入账号:");
int id = scanner.nextInt();
System.out.println("请输入密码:");
String password = scanner.next();
//判断集合的用户是否存在该用户名与密码
//遍历集合的元素,查看是否存在该用户信息
boolean isLogin = false; //定义变量用于记录是否登陆成功的信息  , 默认是没有登陆成功的
Iterator it = users.iterator();
while(it.hasNext()){
User user = (User) it.next();
if(user.id==id&&user.password.equals(password)){
//存在该用户信息,登陆成功...
isLogin = true;
}
}
if(isLogin==true){
System.out.println("欢迎登陆...");
}else{
System.out.println("用户名或者密码错误,登陆失败...");
}
}
public static void reg() {
//110  , 220
User user = null;
while(true){
System.out.println("请输入账号:");
int id = scanner.nextInt();  //220 
user = new User(id,null);
if(users.contains(user)){  // contains底层依赖了equals方法。
//如果存在
System.out.println("该账号已经存在,请重新输入账号");
}else{
//不存在
break;
}
}
System.out.println("请输入密码:");
String password = scanner.next();
user.setPassword(password);
//把user对象保存到集合中
users.add(user);
System.out.println("注册成功!");
System.out.println("当前注册的人员:"+users);
}
}
3.List接口特有的方法
1)集合的体系
Collection 单列集合 的根接口
List  如果是实现了List接口的集合类,该集合类具备的特点:有序,可重复。
Set   如果是实现了Set接口的集合类,该集合类具备的特点: 无序,不可重复。
有序:集合的有序不是指自然顺序,而是指添加进去的顺序与元素出来的顺序是一致的。
例如
2)List接口的特有方法
添加
add(int index, E element) 
addAll(int index, Collection<? extends E> c) 
获取:
get(int index) 
indexOf(Object o) 
lastIndexOf(Object o) 
subList(int fromIndex, int toIndex) 
修改:
set(int index, E element) 
迭代
listIterator() 
 */
public class Demo1 {
public static void main(String[] args) {
List list = new ArrayList();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
list.add("赵六");
System.out.println("集合的元素:"+ list);
}
}
3)集合中的特有方法
import java.util.ArrayList;
import java.util.List;
/*
 List接口中特有方法:
 添加
 add(int index, E element) 
 addAll(int index, Collection<? extends E> c) 
 获取:
 get(int index) 
 indexOf(Object o) 
 lastIndexOf(Object o) 
 subList(int fromIndex, int toIndex) 
 修改:
 set(int index, E element) 
 List接口中特有的方法具备的特点: 操作的方法都存在索引值。
 只有List接口下面的集合类才具备索引值。其他接口下面的集合类都没有索引值。
 ctrl + shift + /  添加多行注释
 ctrl  + shift + \  取消多行注释.
 */
public class Demo2 {


public static void main(String[] args) {
List list = new ArrayList();
list.add("狗娃");
list.add("狗剩");
list.add("铁蛋"); // 把元素添加到集合的末尾处。
list.add("狗娃");
/*
* //添加方法 list.add(1, "赵本山"); // 把元素添加到集合中的指定索引值位置上。 List list2 = new
* ArrayList(); list2.add("本山"); list2.add("小沈阳"); list.addAll(2,list2);
* //把list2的元素添加到list集合指定索引值的位置上。
*/


/*
* // 获取的方法 System.out.println("get方法获取元素:"+list.get(1));
* //根据索引值获取集合中的元素 使用get方法遍历集合的元素: for (int i = 0; i < list.size() ;
* i++) { System.out.print(list.get(i)+","); }
* System.out.println("找出指定元素第一次出现在集合中 的索引值:"+ list.indexOf("本山"));
* System.out.println("找指定的元素最后一次出现在集合中的索引值:"+list.lastIndexOf("狗娃"));
* List subList = list.subList(1, 3); //指定开始与结束的索引值截取集合中的元素。
* System.out.println("子集合的元素是:"+ subList);
*/
list.set(3, "赵本山"); // 使用指定的元素替换指定索引值位置的元素。
System.out.println("集合的元素:" + list);
}
}
3)list结合中的迭代方法listIterator()
ListIterator特有的方法:

 void add(E e) 
          将指定的元素插入列表(可选操作)。
 boolean hasNext() 
          以正向遍历列表时,如果列表迭代器有多个元素,则返回 true(换句话说,如果 next 返回一个元素而不是抛出异常,则返回 true)。
 boolean hasPrevious() 
          如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。
 E
next() 
          返回列表中的下一个元素。
 int nextIndex() 
          返回对 next 的后续调用所返回元素的索引。
 E
previous() 
          返回列表中的前一个元素。
 int previousIndex() 
          返回对 previous 的后续调用所返回元素的索引。
 void remove() 
          从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。
 void set(E e) 
          用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。
package cn.itcast.list;


import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class Demo3 {
public static void main(String[] args) {
List list = new ArrayList();
list.add("狗娃");
list.add("狗剩");
list.add("铁蛋");
list.add("美美");
ListIterator it = list.listIterator(); // 返回的是一个List接口中特有的迭代器
/*
* System.out.println("有上一个元素吗?"+ it.hasPrevious());
* System.out.println("获取上一个元素:"+it.previous()); it.next();
* System.out.println("获取上一个元素:"+ it.previous());
* while(it.hasNext()){ it.next(); }
* while(it.hasPrevious()){ System.out.println("元素:"+ it.previous()); }
* it.next(); it.next(); it.add("张三");
*/
it.next();
it.next();
it.set("张三");
System.out.println("集合的元素:" + list);
}
}
4.迭代器要注意的事项
1) 使用三种方式遍历集合的元素.
第一种: 使用get方法遍历。
第二种: 使用迭代器正序遍历。
第三种: 使用迭代器逆序遍历。
import java.util.List;
import java.util.ArrayList;
import java.util.ListIterator;
public class Demo4 {
public static void main(String[] args) {
List list = new ArrayList();
list.add("张三");
list.add("李四");
list.add("王五");
System.out.println("======get方法遍历=======");
for(int i = 0 ; i<list.size() ; i++){
System.out.print(list.get(i)+",");
}
System.out.println("\r\n======使用迭代器正序遍历==========");
ListIterator it = list.listIterator();//获取到迭代器
while(it.hasNext()){
System.out.print(it.next()+",");
}
System.out.println("\r\n======使用迭代器逆序遍历==========");
while(it.hasPrevious()){
System.out.print(it.previous()+",");
}
}
}
2) 迭代器在变量元素的时候要注意事项
在迭代器迭代元素 的过程中,不允许使用集合对象改变集合中的元素 个数,如果需要添加或者删除只能使用迭代器的方法进行操作。
 如果使用过了集合对象改变集合中元素个数那么就会出现ConcurrentModificationException异常。
 迭代元素 的过程中: 迭代器创建到使用结束的时间。
public class Demo5 {
public static void main(String[] args) {
List list = new ArrayList();
list.add("张三");
list.add("李四");
list.add("王五");
ListIterator it = list.listIterator();//获取到迭代器
/* while(it.hasNext()){
System.out.print(it.next()+",");
//it.add("aa"); // 把元素添加到当前指针指向位置
list.add("aa");  // add方法是把元素添加到集合的末尾处的。
// list.remove("张三");
}*/

list.add("aa");
it.next();
System.out.println("\r\n集合的元素:"+ list);
}
}
5.ArrayList的原理
a.集合的体系
Collection  单列集合的根接口
List 如果实现了List接口的集合类,具备的特点: 有序,可重复。
ArrayList   ArrayList 底层是维护了一个Object数组实现 的, 特点: 查询速度快,增删慢。
什么时候使用ArrayList: 如果目前的数据是查询比较多,增删比较少的时候,那么就使用ArrayList存储这批数据。比如 :高校的 图书馆
b.ArrayList的构造方法
ArrayList() 
          构造一个初始容量为 10 的空列表。 
ArrayList(Collection<? extends E> c) 
          构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。 
ArrayList(int initialCapacity) 
          构造一个具有指定初始容量的空列表。
c.ArrayList的方法摘要
boolean add(E e) 
          将指定的元素添加到此列表的尾部。 
 void add(int index, E element) 
          将指定的元素插入此列表中的指定位置。 
 boolean addAll(Collection<? extends E> c) 
          按照指定 collection 的迭代器所返回的元素顺序,将该 collection 中的所有元素添加到此列表的尾部。 
 boolean addAll(int index, Collection<? extends E> c) 
          从指定的位置开始,将指定 collection 中的所有元素插入到此列表中。 
 void clear() 
          移除此列表中的所有元素。 
 Object clone() 
          返回此 ArrayList 实例的浅表副本。 
 boolean contains(Object o) 
          如果此列表中包含指定的元素,则返回 true。 
 void ensureCapacity(int minCapacity) 
          如有必要,增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数。 
方法摘要
 boolean add(E e) 
          将指定的元素添加到此列表的尾部。
 void add(int index, E element) 
          将指定的元素插入此列表中的指定位置。
 boolean addAll(Collection<? extends E> c) 
          按照指定 collection 的迭代器所返回的元素顺序,将该 collection 中的所有元素添加到此列表的尾部。
 boolean addAll(int index, Collection<? extends E> c) 
          从指定的位置开始,将指定 collection 中的所有元素插入到此列表中。
 void clear() 
          移除此列表中的所有元素。
 Object
clone() 
          返回此 ArrayList 实例的浅表副本。
 boolean contains(Object o) 
          如果此列表中包含指定的元素,则返回 true。
 void ensureCapacity(int minCapacity) 
          如有必要,增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数。
 E
get(int index) 
          返回此列表中指定位置上的元素。
 int indexOf(Object o) 
          返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1。
 boolean isEmpty() 
          如果此列表中没有元素,则返回 true
 int lastIndexOf(Object o) 
          返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1。
 E
remove(int index) 
          移除此列表中指定位置上的元素。
 boolean remove(Object o) 
          移除此列表中首次出现的指定元素(如果存在)。
protected  void removeRange(int fromIndex, int toIndex) 
          移除列表中索引在 fromIndex(包括)和 toIndex(不包括)之间的所有元素。
 E
set(int index, E element) 
          用指定的元素替代此列表中指定位置上的元素。
 int size() 
          返回此列表中的元素数。
 Object[]
toArray() 
          按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。
<T> T[]
toArray(T[] a) 
          按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。
 void trimToSize() 
          将此 ArrayList 实例的容量调整为列表的当前大小。
LinkedList
----------------| Vector(了解即可)
----------------| Set  如果实现了Set接口的集合类, 具备的特点: 无序,不可重复。
6.ArrayList的练习需求
package cn.itcast.list;
import java.util.ArrayList;
import java.util.Iterator;
class Book{
int id;
String name;// 名字
public Book(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "{ 书号:"+ this.id+" 书名:"+ this.name+" }";
}
@Override
public boolean equals(Object obj) {
Book book =(Book)obj;
return this.id==book.id;
}
}
// 需求: 编写一个函数清除集合中重复元素。 如果书号是一样就视为重复元素。  要求: 遍历集合元素的时候必须使用迭代器。  get 迭代器
public class Demo7 {
public static void main(String[] args) {
ArrayList list=  new ArrayList();
list.add(new Book(110,"java编程思想"));
list.add(new Book(220,"java核心技术"));
list.add(new Book(330,"深入javaweb"));
list.add(new Book(110,"javas神书"));
ArrayList list2 = clearRepeat(list);
System.out.println("新集合的元素是:"+ list2);
}
public static ArrayList  clearRepeat(ArrayList list){
//创建一个新的集合
ArrayList newList = new ArrayList();
//获取迭代器
Iterator it = list.iterator();
while(it.hasNext()){
Book book = (Book) it.next();  //从旧集合中获取的元素
if(!newList.contains(book)){
//如果新集合没有包含该书籍,那么就存储到新集合中
newList.add(book);
}
}
return newList;
}
}
7.LinkedList的实现原理
使用链表数据结构实现的。特点:查询速度慢,增删快
8.LinkedList的方法
LinkedList中的特有方法
1:方法介绍
 void addFirst(E e) 
          将指定元素插入此列表的开头。
 void addLast(E e) 
          将指定元素添加到此列表的结尾。
 E
getFirst() 
          返回此列表的第一个元素。
 E
getLast() 
          返回此列表的最后一个元素。
E
removeFirst() 
          移除并返回此列表的第一个元素。
 E
removeLast() 
          移除并返回此列表的最后一个元素。
2:数据结构
1)栈 (1.6)  : 主要是用于实现堆栈数据结构的存储方式。
先进后出


void push(E e) 
          将元素推入此列表所表示的堆栈。
 E
pop() 
          从此列表所表示的堆栈处弹出一个元素。
2)队列(双端队列1.5): 主要是为了让你们可以使用LinkedList模拟队列数据结构的存储方式。
先进先出
 boolean offer(E e) 
          将指定元素添加到此列表的末尾(最后一个元素)。
 E
poll() 
          获取并移除此列表的头(第一个元素)
3)返回逆序的迭代器对象      
Iterator<E>
descendingIterator() 
          返回以逆向顺序在此双端队列的元素上进行迭代的迭代器。
4)LinkedList特有方法实例
public class Demo8 {


public static void main(String[] args) {
LinkedList list = new LinkedList();
list.add("张三");
list.add("李四");
list.add("王五");
/*
* list.addFirst("狗娃"); //把元素添加到集合的首位置上。 list.addLast("狗剩");
* //把元素添加到集合的末尾处。
 
* System.out.println("获取集合中首位置的元素:"+list.getFirst());
* System.out.println("获取集合中末尾的元素:"+ list.getLast());

* System.out.println("删除集合中的首位置元素并返回:"+ list.removeFirst());
* System.out.println("删除集合中的末尾素并返回:"+ list.removeLast());
 
* list.push("狗娃"); //将该元素插入此集合的开头处。
* System.out.println("删除集合的首元素:"+list.pop()); // 移除并返回集合中的第一个元素


* list.offer("狗剩"); System.out.println("删除集合的首元素: "+list.poll());
* System.out.println("集合中的元素:"+ list);
*/
Iterator it = list.descendingIterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
5)LinkedList的堆和列
import java.util.LinkedList;
/*
 1:栈 (1.6)  : 主要是用于实现堆栈数据结构的存储方式。
 先进后出
 push() 
 pop()
 2:队列(双端队列1.5): 主要是为了让你们可以使用LinkedList模拟队列数据结构的存储方式。
 先进先出
 offer()
 poll()
 机试题目: 使用LinkedList实现堆栈数据结构的存储方式与队列的数据结构存储方式。
 */
// 使用LinkedList模拟堆栈的数据结构存储方式
class StackList {
LinkedList list;
public StackList() {
list = new LinkedList();
}
// 进栈
public void add(Object o) {
list.push(o);
}
// 弹栈 : 把元素删除并返回。
public Object pop() {
return list.pop();
}
// 获取元素个数
public int size() {
return list.size();
}
}
// 使用LinkedList模拟队列的存储方式
class TeamList {
LinkedList list;
public TeamList() {
list = new LinkedList();
}


public void add(Object o) {
list.offer(o);
}
public Object remove() {
return list.poll();
}
// 获取元素个数
public int size() {
return list.size();
}
}
public class Demo9 {
public static void main(String[] args) {
TeamList list = new TeamList();
list.add("李嘉诚");
list.add("马云");
list.add("王健林");
int size = list.size();
for (int i = 0; i < size; i++) {
System.out.println(list.remove());
}


}
}