【集合】List接口
一、什么是List
List是继承自Collection是一个接口,其在java.util.List中定义。
public interface List<E> extends Collection<E> {
....
}
为什么定义了Collection和List两级Interface?其接口表达的概念不同:
-
Collection中描述的是集合。其想表达的概念的属性:
- 元素可以 有重复。
- 也可以 禁止元素重复。
- 可以强制使用特定的 顺序。
- 也可以不强制有 顺序。
-
List描述的是个列表,描述的 可存放重复元素,元素存取是有序 的集合。List特点:
- 一组 有序 对象和集合。
- 每个对象都有 特定位置 。
- List中 允许重复 的对象。
- List支持根据 索引 查询,根据 索引 设定元素的值。
- List有点类似数组,但是List的 大小按需变化,以适应元素数量的需要。
-
Collection还有另外一个扩展接口Set,描述的是 不可以存放重复元素,元素存取是无序 的集合。
二、List新定义的接口
既然List表达的是元素可重复、有顺序概念。相应的,增加了指定顺序索引的操作接口。如下;
1. 增加元素
(1)指定索引,插入1个元素
void add(int index, E element);
通过如上方法向List的实现类中插入元素,主要其索引不能出现跳过现象。样例:
List<String> string = new ArrayList<String>();
string.add("hello");
System.out.println(string.size()); //size是1
string.add("World");
System.out.println(string.size()); //size是2
string.add("!");
System.out.println(string.size()); //size是3
string.add(2, "ok");
System.out.println(string.size()); //size是4
//string.add(4, "xxx"); //OK
string.add(5, "xxx"); //失败
如上样例:因为前面已经有4个元素,索引是0~3。所以最后一句,指定index=4插入元素是可以的。 但是,如果是string.add(5, "xxx"),由于已有索引是0~3,无法跳过索引4直接在索引5插入元素,报Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 5, Size: 4错误。
(2)指定索引,插入参数集合中的所有元素
boolean addAll(int index, Collection<? extends E> c);
2. 删除元素
(1)指定索引,删除指定元素
E remove(int index);
3.修改元素
(1)指定索引,修改指定位置元素
E set(int index, E element);
4. 查找元素
(1)指定索引,查找指定位置元素。
E get(int index);
(2)指定元素,正向查找其在列表中的位置。
int indexOf(Object o);
(3)指定元素,反向向查找其在列表中的位置。
int lastIndexOf(Object o);
(4)指定起、止索引,返回子列表
List<E> subList(int fromIndex, int toIndex);
【注意】1:
subList()返回的类型是一个叫SubList的内存类的类型,类型定义如下:
public abstract class AbstractCollection<E> implements Collection<E>
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>
private class SubList extends AbstractList<E> implements RandomAccess
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
subList和ArrayList类的关系如下:
List(接口) <---实现--- AbstractList(虚拟类) <---继承--- SubList(实现类)
所以,suListb()返回的结果,不能直接赋值给ArrayList类型的引用。如下是错误的:
List<String> list = new ArrayList<>();
.....
ArrayList<String> subList = (ArrayList<String>) list.subList(0,0);
【注意】2:
subList()返回的子列表变更会回馈父列表。即:只要修改了子列表,父列表立即就能察觉到变化。如果不想要这种反馈,可通过new方式建立子列表的副本。如下:
List<String> subcopy = new ArrayList<String>(list.subList(1,3));