Java基础之Collections框架List接口及其源码分析
List接口的特点索引访问搜索迭代范围视图
List简单实例List源码分析
有序集合(也称为序列)。 用户可以精确控制列表中每个元素的插入位置。 用户可以通过其整数索引(列表中的位置)访问元素,并在列表中搜索元素。
与集合不同,列表通常允许重复的元素。 更正式地说,列表通常允许成对的元素e1和e2,使得e1.equals(e2),并且如果它们完全允许空元素,则它们通常允许多个空元素。
List接口在Iterator的协定,add,remove,equals和hashCode方法的协定上放置了除Collection接口中指定的规定以外的其他规定。 为了方便起见,还包含其他继承方法的声明。
List接口提供了四种位置(索引)访问列表元素的方法。 列表(如Java数组)从零开始。 请注意,对于某些实现(例如LinkedList类),这些操作可能在时间上与索引值成比例执行。 因此,如果调用者不知道实现,则遍历列表中的元素通常比对其进行索引更可取。
List接口提供了一个称为ListIterator的特殊迭代器,除了Iterator接口提供的常规操作之外,该迭代器还允许元素插入和替换以及双向访问。 提供一种获取列表迭代器的方法,该列表迭代器从列表中的指定位置开始。
List接口提供了两种搜索指定对象的方法。 从性能的角度来看,应谨慎使用这些方法。 在许多实现中,它们将执行昂贵的线性搜索。
List接口提供了两种方法,可以有效地在列表中的任意点插入和删除多个元素。
注意:虽然允许列表将自身包含为元素,但建议格外小心:equals和hashCode方法在这样的列表上不再定义良好。
List接口的特点
索引访问
根据元素在列表中的数字位置操作元素。 这包括诸如get,set,add,addAll和remove之类的方法。
//获取元素 索引从0开始
int index = 0;
list.get(index);
搜索
在列表中搜索指定的对象并返回其数字位置。 搜索方法包括indexOf和lastIndexOf。
String index= “tony”;
list.indexOf(index); //获取tony元素的下标
迭代
扩展Iterator语义以利用列表的顺序性质。 ListIterator方法提供了此行为。
public int indexOf(E e) {
for (ListIterator<E> it = listIterator(); it.hasNext(); )
if (e == null ? it.next() == null : e.equals(it.next()))
return it.previousIndex();
// Element not found
return -1;
}
范围视图
子列表方法对列表执行任意范围操作。
int fromIndex = 1,toIndex = 5;
list.subList(fromIndex, toIndex)
Java平台包含两个通用的List实现。ArrayList通常是性能更好的实现,而LinkedList在某些情况下性能更好。像Set接口一样,List增强了对equals和hashCode方法的要求,因此可以比较两个List对象的逻辑相等性,而不必考虑它们的实现类。 如果两个List对象包含相同顺序的相同元素,则它们相等。
List简单实例
交换list中指定位置的值
//i和j是list中要替换元素的下标
public static <String> void swap(List<String> a, int i, int j) {
String tmp = a.get(i);
a.set(i, a.get(j));
a.set(j, tmp);
}
//将list中的元素打乱
public static void shuffle(List<String> list, Random rnd) {
for (int i = list.size(); i > 1; i--)
swap(list, i - 1, rnd.nextInt(i));
}
public static void main(String[] args) {
if (args.length < 2) {
return;
}
int numHands = Integer.parseInt(args[0]);
int cardsPerHand = Integer.parseInt(args[1]);
String[] suit = new String[] {
"spades", "hearts",
"diamonds", "clubs"
};
String[] rank = new String[] {
"ace", "2", "3", "4",
"5", "6", "7", "8", "9", "10",
"jack", "queen", "king"
};
List<String> deck = new ArrayList<String>();
for (int i = 0; i < suit.length; i++)
for (int j = 0; j < rank.length; j++)
deck.add(rank[j] + " of " + suit[i]);
//Collections集合处理类
Collections.shuffle(deck);
if (numHands * cardsPerHand > deck.size()) {
System.out.println("Not enough cards.");
return;
}
for (int i = 0; i < numHands; i++)
System.out.println(dealHand(deck, cardsPerHand));
}
public static <E> List<E> dealHand(List<E> deck, int n) {
int deckSize = deck.size();
List<E> handView = deck.subList(deckSize - n, deckSize);
List<E> hand = new ArrayList<E>(handView);
handView.clear();
return hand;
}
List源码分析
public interface List<E> extends Collection<E> {
/**
返回list中的元素个数
*/
int size();
/**
判断list是否为空
*/
boolean isEmpty();
/**
返回list是否包含指定的元素
*/
boolean contains(Object o);
/**
返回迭代器
*/
Iterator<E> iterator();
/**
将list转换为数组
*/
Object[] toArray();
/**
返回指定类型的数组
*/
<T> T[] toArray(T[] a);
/**
添加元素
*/
boolean add(E e);
/**
移除元素
*/
boolean remove(Object o);
/**
是否包含指定集合中的所有元素
*/
boolean containsAll(Collection<?> c);
/**
添加指定集合中的所有元素到list中
*/
boolean addAll(Collection<? extends E> c);
/**
在指定的位置将指定集合中的元素添加到list中
*/
boolean addAll(int index, Collection<? extends E> c);
/**
移除指定集合中在list中的所有元素
*/
boolean removeAll(Collection<?> c);
/**
removeAll取反
*/
boolean retainAll(Collection<?> c);
/**
用将该运算符应用于该元素的结果替换此列表中的每个元素。
*/
default void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
//通过迭代器遍历替换 同时operator获取元素
final ListIterator<E> li = this.listIterator();
while (li.hasNext()) {
li.set(operator.apply(li.next()));
}
}
/**
*/
@SuppressWarnings({"unchecked", "rawtypes"})
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
//将list转为数组,通过Arrays的sort方法进行排序
Arrays.sort(a, (Comparator) c);
//进行迭代器进行迭代设置值达到排序
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
/**
清除list中的所有元素
*/
void clear();
/**
比较list是否相等
个数和包含的元素
*/
boolean equals(Object o);
/**
返回list的hash值,将list中的每一个元素的hashCode进行相加
*/
int hashCode();
/**
获取指定位置的元素
*/
E get(int index);
/**
给指定的索引设置值
*/
E set(int index, E element);
/**
向指定的位置添加一个元素
*/
void add(int index, E element);
/**
移除指定索引下的元素
*/
E remove(int index);
/**
返回元素的list中的索引
*/
int indexOf(Object o);
/**
返回相关元素最后出现的索引值
*/
int lastIndexOf(Object o);
/**
返回list特殊的List迭代器
*/
ListIterator<E> listIterator();
/**
返回此列表中元素的列表迭代器(正确序列),从列表中的指定位置开始。
*/
ListIterator<E> listIterator(int index);
/**
返回指定位置之间此列表部分的视图 fromIndex (含)和toIndex(不包含)
如果相等将返回一个空的list
返回的列表由该列表支持,因此是非结构化的返回列表中的更改会反映在此 列表中,反之亦然。返回的列表支持所有支持的可选列表操作通过此列表
*/
List<E> subList(int fromIndex, int toIndex);
/**
返回一个Spliterator实例
*/
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.ORDERED);
}
}
相关的方法的实现是通过List的两个实现类ArrayList,LinkedList去实现的。默认方法 relaceAll和sort是jdk 8中支持的语法。这个是在List接口中实现。里面涉及了Collections类和Arrays类,这个可以认为是集合操作的相关工具类。到时候研究,哈哈!