Collection类的shuffle()、sort()、binarySearch()

Collection类的shuffle方法

1、 RandomAccess是一个标记接口,没有任何实现方法。实现这个接口仅仅是为了表明随机访问( random access )比较快。比如,实现了这个接口的List,其

(注:Less than ( < =  &lt; ) and greater than ( >  &gt;  ))
   
   
for (int i=0, n=list.size(); i < n; i++)
list.get(i);
访问要快于

   
   
for (Iterator i=list.iterator(); i.hasNext(); )
i.next();

ArrayList和Vector实现了这个接口。

2、Collections中的shuffle()方法。

该方法有如下两个不同的重载形式。
   
   
public static void shuffle(List<?> list, Random rnd)
public static void shuffle(List<?> list)

如果没有指定shuffle的Random,就创建一个默认的 Random r=new Random():

   
   
public static void shuffle(List<?> list) {
Random rnd = r;
if (rnd == null)
r = rnd = new Random();
shuffle(list, rnd);
}
private static Random r;

在这个方法中,依次从最后一个元素逆序到第二个元素,每到一个元素,随机地选取List中的一个元素与其交换。如果List元素个数比较多而且没有实现随机访问的话(对于List而言就是没有实现 RandomAccess接口 ),这个“ 随机地选取List中的一个元素 ”性能比较差,所以首先将List中的元素拷贝到数组中,因为数组支持根据下标随机访问。等shuffle完毕后将shuffle后的数据拷贝到List中:

   
   
public static void shuffle(List<?> list, Random rnd) {
int size = list.size();
if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
for (int i=size; i>1; i--)
swap(list, i-1, rnd.nextInt(i));
} else {
Object arr[] = list.toArray();
// Shuffle array
for (int i=size; i>1; i--)
swap(arr, i-1, rnd.nextInt(i));
// Dump array back into list
ListIterator it = list.listIterator();
for (int i=0; i<arr.length; i++) {
it.next();
it.set(arr[i]);
}
}
}

3、Collections中的sort()方法。
对List中的元素进行排序。
  
  
public static <T extends Comparable<? super T>> void sort(List<T> list)
public static <T> void sort(List<T> list, Comparator<? super T> c)

 如果没有指定 Comparator, 则List中的元素必定要实现Comparable接口!
List必须是可修改的(支持set()),不必是可改变大小的(支持add()、remove()方法)。稳定的排序算法。
方法的实现过程是将所有元素复制到一个数组,然后再将数组中排序好的元素copy回List中。数组中排序使用的是变形的归并排序。

   
   
public static <T extends Comparable<? super T>> void sort(List<T> list) {
Object[] a = list.toArray();
Arrays.sort(a);
ListIterator<T> i = list.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set((T)a[j]);
}
}

   
   
public static <T> void sort(List<T> list, Comparator<? super T> c) {
Object[] a = list.toArray();
Arrays.sort(a, (Comparator)c);
ListIterator i = list.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set(a[j]);
}
}
如果是ArrayList,为什么还要复制到数组再排序呢?应该可以直接排序啊???


4、Collections中的 binarySearch ()方法。    
   
   
   
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)

如果List没有实现RandomAccess接口,即不支持随机访问,且List中元素数量较多,则调用   iteratorBinarySearch   方法,否则直接 调用 indexedBinarySearch方法。 indexedBinarySearch中根据下标直接取值,而 iteratorBinarySearch   根据 ListIterator取特定下标处的值:

   
   
public static <T>
int binarySearch(List<? extends Comparable<? super T>> list, T key) {
if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
return Collections.indexedBinarySearch(list, key);
else
return Collections.iteratorBinarySearch(list, key);
}

   
   
private static <T>
int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key)
{
int low = 0;
int high = list.size()-1;
while (low <= high) {
int mid = (low + high) >>> 1;
Comparable<? super T> midVal = list.get(mid);
int cmp = midVal.compareTo(key);
if (cmp < 0)
low = mid + 1;
else if (cmp > 0)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found
}

   
   
private static <T>
int iteratorBinarySearch(List<? extends Comparable<? super T>> list, T key)
{
int low = 0;
int high = list.size()-1;
ListIterator<? extends Comparable<? super T>> i = list.listIterator();
while (low <= high) {
int mid = (low + high) >>> 1;
Comparable<? super T> midVal = get(i, mid); //这里变成了线性查找啊啊啊啊啊
int cmp = midVal.compareTo(key);
if (cmp < 0)
low = mid + 1;
else if (cmp > 0)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found
}

   
   
private static <T> T get(ListIterator<? extends T> i, int index) {
T obj = null;
int pos = i.nextIndex();
if (pos <= index) {
do {
obj = i.next();
} while (pos++ < index);
} else {
do {
obj = i.previous();
} while (--pos > index);
}
return obj;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值