Colletion的一些api
Collection工具类
现在已经实现List接口的实现类有:
AbstractList, AbstractSequentialList(抽象类)
ArrayList,LinkedList, Stack, Vector(常用)
AttributeList,CopyOnWriteArrayList,RoleList, RoleUnresolvedList
void swap(List list, int i , int j)//交换两个索引位置的元素
swap方法源码:
@SuppressWarnings({"rawtypes", "unchecked"})
public static void swap(List<?> list, int i, int j) {
// instead of using a raw type here, it's possible to capture
// the wildcard but it will require a call to a supplementary
// private method
final List l = list;
l.set(i, l.set(j, l.get(i)));
}
swap方法很简单,
1.l.get(i):获取下标i对应的元素
2.l.set(j, l.get(i)) 将下标i对应的元素付给下标为j的元素,并j原来的元素返回
3.l.set(i, l.set(j, l.get(i)))最后将返回的j元素原来的值赋给下标为i的元素
void reverse(List list)//反转
reverse方法源码:
private static final int REVERSE_THRESHOLD = 18;
@SuppressWarnings({"rawtypes", "unchecked"})
public static void reverse(List<?> list) {
int size = list.size();
if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) {
for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--)
swap(list, i, j);
} else {
// instead of using a raw type here, it's possible to capture
// the wildcard but it will require a call to a supplementary
// private method
ListIterator fwd = list.listIterator();
ListIterator rev = list.listIterator(size);
for (int i=0, mid=list.size()>>1; i<mid; i++) {
Object tmp = fwd.next();
fwd.set(rev.previous());
rev.set(tmp);
}
}
}
从源码中我们可以看到,reverse()方法支持传入List类型(List只是一个接口),
对于reverse()方法先获取list的size,如果list的size小于18,或者实现了RandomAccess(随机读写接口),会通过调用swap方法将前后的元素对调
如果不符合要求上面两铬条件的一条,则分别生成指针在初始和末尾的两个迭代器,通过tmp这个中间变量,将前后元素对调
void rotate(List list, int distance)/旋转。当distance为正数时,将list后distance个元素整体移到前面。当distance为负数时,将 list的前distance个元素整体移到后面。
public static void rotate(List<?> list, int distance) {
if (list instanceof RandomAccess || list.size() < ROTATE_THRESHOLD)
rotate1(list, distance);
else
rotate2(list, distance);
}
private static <T> void rotate1(List<T> list, int distance) {
int size = list.size();
if (size == 0)
return;
distance = distance % size;
if (distance < 0)
distance += size;
if (distance == 0)
return;
for (int cycleStart = 0, nMoved = 0; nMoved != size; cycleStart++) {
T displaced = list.get(cycleStart);//获取元素
int i = cycleStart;
do {
i += distance;//将要旋转到的位置
if (i >= size)
i -= size;
displaced = list.set(i, displaced);//将位置旋转,并将被替换的元素赋给displaced
nMoved ++;
} while (i != cycleStart);
}
}
如果元素数量少,或者实现了随机读取接口执行rotate1方法,先将传入的distance对list长度取模,如果为负数,则将distance加上list长度,转换为相应的正数,然后是一个for循环嵌套一个do-while循环。
For循环中的判断条件为nMoved != size 也就是说,只有所有元素都调换了一遍之后,循环才会结束。
里层为do-while循环,
首先将i位置的元素旋转到他该到的位置
1.确定元素要旋转到的位置 i += distance;if (i >= size) i -= size;
2.将其替换,并获取被替换的值 displaced = list.set(i, displaced);
3.一个元素已经旋转到指定位置 nMoved+1
4.判断while条件,while(i != cycleStart)
//如果distance和size是倍数关系,在未完全旋转时while会结束,继续执行for循环,如果distance与size不是倍数关系,则在while循环中进行全部旋转for循环内的语句只走一次
private static void rotate2(List<?> list, int distance) {
int size = list.size();
if (size == 0)
return;
int mid = -distance % size;
if (mid < 0)
mid += size;
if (mid == 0)
return;
reverse(list.subList(0, mid));
reverse(list.subList(mid, size));
reverse(list);
}
对于distance的处理rotate1与rotate2是不同的,
1.首先求出mid值,mid代表的是要旋转到第一位的元素
2.然后对(0,mid)做翻转,再对(mid,size)做翻转,最后将整个list做翻转,就得到了旋转后的结果。
//至于为啥我暂时也搞不清楚
int binarySearch(List list, Object key)
//对List进行二分查找,返回索引,注意List必须是有序的
int max(Collection coll)
//根据元素的自然顺序,返回最大的元素。 类比int min(Collection coll)
int max(Collection coll, Comparator c)
//根据定制排序,返回最大元素,排序规则由Comparatator类控制。类比int min(Collection coll, Comparator c)
void fill(List list, Object obj)
//用指定的元素代替指定list中的所有元素。
int frequency(Collection c, Object o)
//统计元素出现次数
int indexOfSubList(List list, List target)
//统计target在list中第一次出现的索引,找不到则返回-1,类比int lastIndexOfSubList(List source, list target).
boolean replaceAll(List list, Object oldVal, Object newVal)
// 用新元素替换旧元素
Array的常用api
排序 : sort()
查找 : binarySearch()
比较: equals()
填充 : fill()
转列表: asList()
转字符串 : toString()
复制: copyOf()