List接口是Collection接口的一个子接口,继承了Colelction中的方法,同时还有自己的方法
主要有以下几种
1.void add(int index,object element):在指定索引位置添加元素,添加在中间位置时,后面的元素依次往后移置,添加的位置可以在最后一位,但添加的索引位置不能越界,否则异常IndexOutOfBoundsException
2.Object get(int index):获取指定位置的元素,索引不能越界,否则报错IndexOutOfBoundsException
3.Objec remove(int index):删除指定位置的元素,并返回该位置的元素,索引位置不能越界,否则报错IndexOutOfBoundsException
4.Object set(int index):将指定位置的元素修改,返回修改之前该位置的元素
,并返回当前位置的旧元素
list接口特有方法的使用示例
import java.util.ArrayList;
import java.util.List;
import students.Student;
public class ListTest01 {
public static void main(String[] args) {
List l = new ArrayList();
l.add(new Student(12, "张"));
l.add(new Student(13, "李"));
l.add(2, new Student(14, "赵"));
l.add(3, "a");
addTest(l);
getTest(l);
removeTest(l);
setTest(l);
}
public static void setTest(List l) {
// set(int index,Object element)
System.out.println(l);
Object o5 = l.set(1, "E");
System.out.println(l);
System.out.println(o5);
// Object o6 = l.set(10, "S");//索引位置超过list长度,报错IndexOutOfBoundsException
}
public static void removeTest(List l) {
// remove(int index)
Object o3 = l.remove(3);
System.out.println(o3);
// Object o4 = l.remove(8);// 索引位置超过list长度,报错IndexOutOfBoundsException
}
public static void getTest(List l) {
// get(int index)
Object o1 = l.get(1);// 多态,返回值是元素的对象类型
Student s1 = (Student) o1;// 向下转型,不转的话也可以调用子类toString方法
System.out.println(s1);
Object o2 = l.get(4);
Student stu1 = (Student) o2;// 向下转型,不转的话是Object类型,也可以调用子类Student的方法
System.out.println(stu1);
// Object o2=l.get(8);//// 索引位置超过list长度,报错IndexOutOfBoundsException
}
public static void addTest(List l) {
// add(int index,Object element)
l.add(4, new Student(15, "刘"));
// l.add(7, "d");//索引位置超过list长度,报错IndexOutOfBoundsException
}
}
out:
Student [age=13, name=李]
Student [age=15, name=刘]
a
[Student [age=12, name=张], Student [age=13, name=李], Student [age=14, name=赵], Student [age=15, name=刘]]
[Student [age=12, name=张], E, Student [age=14, name=赵], Student [age=15, name=刘]]
Student [age=13, name=李]
Iterator和ListIterator的区别
实现了Collection接口的集合类及子类,都有Iterator方法,返回一个实现了Iterator接口的实例。
在List接口及其实现它的子类如ArrayList、LinkedList和Vector的中还有一个ListIterator
在list接口的实现类ArrayList里,Iterator和ListIterator这两个内部类的定义如下(LinkedList,Vector中类似)
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
// prevent creating a synthetic constructor
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];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
@Override
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int size = ArrayList.this.size;
int i = cursor;
if (i < size) {
final Object[] es = elementData;
if (i >= es.length)
throw new ConcurrentModificationException();
for (; i < size && modCount == expectedModCount; i++)
action.accept(elementAt(es, i));
// update once at end to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
/**
* An optimized version of AbstractList.ListItr
*/
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
super();
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[lastRet = i];
}
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.set(lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void add(E e) {
checkForComodification();
try {
int i = cursor;
ArrayList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
使用迭代器next()方法获得的元素是一个集合中对应元素的深拷贝,如果对迭代变量进行修改是不会修改集合中的原数据的。
迭代器Iterator是对真实集合的一个映射,如果要修改迭代器中的元素,迭代器先对映射进行修改,再将映射的改动更新到真实集合数据,反向不成立,因为迭代器知道自己是哪个真实集合数据的映射,而真实集合数据不知道它与哪些映射相关联,如果在迭代器使用过程中集合修改了自身的数据,那么使用与它相关联的迭代器就会报错,
ListIterator是Iterator的一个子接口,
定义了一个油表指针,在[0,size]之间移动,比如正向遍历一遍,
List list=new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
ListIterator lit=list.ListIterator();
while(lit.hasnext()){
System.out.println(lit.next())
}
之后,该迭代器中的游标值变为4,
定义的方法有:
void add(E e) 在游标指针前面插入一个元素,即如果往后遍历的情况下,游标指向的是add(元素)右边的那个元素
boolean hasNext() 判断游标处是否有元素,实现方法是判断游标是否等于size,等于size时返回false,即游标已经超过集合的索引,此方法是继承子Iterator接口的方法
boolean hasPrevious() 判断游标是否有前一个元素,实现方法是游标是否等于0,
E next() 返回当前游标处的元素,游标后移,E previous() 返回当前游标下的元素,并将游标向前移动一位
int nextIndex() 返回当前游标的值,int previousIndex() 返回当前(游标-1)这个值
void remove() 删除迭代器最后一次操作的元素,这个元素必须是next()方法或者previous()方法返回的元素,删除后,后面的元素依次左移一位,游标也左移一位,因为它指向的那个元素左移了一位,游标指向的元素不变
void set(E e) 替换一个next()方法或者previous()方法返回的元素,此方法不能用在remove和add之后,因为添加或者删除元素后游标不再指向那个返回的对象,就无法修改了,会报错
示例:
//测试在iterator迭代的时候修改集合元素
public class ListIteratorTest01 {
public static void main(String[] args) {
List list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
Iterator it = list.iterator();
// list.remove(2);//此行代码报错,因为在创建迭代器之后修改集合数据,而迭代器不知道,所以报错
while (it.hasNext()) {
String s = (String) it.next();
System.out.println(s);
}
Iterator it1 = list.iterator();
while (it1.hasNext()) {
String s1 = (String) it1.next();
if (s1.equals("b")) {
// list.add("g");//这两行代码都在迭代器使用过程中,集合对其修改,迭代器却不知道,所以报错
// list.remove(2);//ConcurrentModificationException
}
}
Iterator it2 = list.iterator();
while (it2.hasNext()) {
String s2 = (String) it2.next();
if (s2.equals("b")) {
it2.remove();// 调用迭代器的方法修改,迭代器自身变化后,再去修改集合中的值
System.out.println(list);
}
}
}
}
out:
a
b
c
d
e
[a, c, d, e]
//测试ListIterator的部分方法,
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListIteratorTest {
public static void main(String[] args) {
List list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
ListIterator iti = list.listIterator();
while (iti.hasNext()) {
String s3 = (String) iti.next();
System.out.println(s3);
if (s3.equals("b")) {
// 将迭代器返回的对象修改,此方法不能用在remove和add之后,
iti.set("k");// list=[a, k, c, d, e]
// 删除迭代器返回的那个对象,如果被修改,就删除哪个修改后的对象
iti.remove();// list= [a, c, d, e]
// 迭代器在当前next()方法返回值的值的后面添加元素,再将映像更新到集合中
iti.add("h");//[a, h, c, d, e]
// iti.set("k");
}
}
System.out.println(list);
// 执行完一遍正向遍历后,游标值等于6,等于size值,可以反向遍历
System.out.println("------------");
while (iti.hasPrevious()) {
System.out.print(iti.nextIndex());
System.out.println(iti.previous());
}
}
}
out:
a
b
c
d
e
[a, h, c, d, e]
------------
5e
4d
3c
2h
1a
参考Iterator和集合的映射部分https://blog.csdn.net/japson_iot/article/details/79010998