Collections中sort(),binarySearch(), shuffle()源代码的简单分析

本文深入探讨Java集合框架中的排序与搜索优化技术,包括Collections类如何避免链表结构排序带来的性能瓶颈,通过将List转换为数组,利用Arrays.sort()方法实现高效排序,并介绍TimSort与LegacyMergeSort的区别;同时解释了binarySearch方法的实现,以及针对不同大小链表的indexBinarySearch()和iteratorBinarySearch()方法的区别;最后讨论了shuffle方法在链表排序时的特殊策略。
  • sort()
    可以看到,Collections并不是直接对List进行排序操作,这是因为排序过程中可能会涉及大量的随机访问,类似于LinkedList这样的链表结构就会十分耗时。所以先将List转换为Arrays(普通数组),然后调用Arrays.sort()进行排序
    完成排序之后,再一个一个地,把Arrays的元素复制到List中
    
    在Arrays.sort()方法中,由LegacyMergeSort.userRequested决定是采用MergeSort还是TimSort。
   
    LegacyMergeSort.userRequested由"java.util.Arrays.useLegacyMergeSort"设置。
    TimSort是改进后的归并排序,对归并排序在已经反向排好序的输入时表现为O(n^2)的特点做了特别优化。对已经正向排好序的输入减少回溯。对两种情况(一会升序,一会降序)的输入处理比较好(摘自百度百科)。

  • binarySearch()
    binarySearch存在两种方法:indexedBinarySearch()和iteraotrBinarySearch(),前者针对具备随机存取能力的List以及小的链表,后者适用于大的链表。

              

                  BINARYSEARCH_THRESHOLD用于判断一个链表是大还是小,它的值为5000

    
    indexBinarySearch()和iteratorBinarySearch()只在一个地方存在区别。

                   indexBinarySearch():

             

                    iteratorBinarySearch():

             

    可以看到,它们在取midVal采用了不同的方法。前者使用了list默认的get()方法,后者使用了Collections.get()方法。
    对于链表而言,区别在于:list默认的get()方法每次都是从头部开始遍历,直到指定位置。Collections.get()方法会记住上次查询的位置,然后从该位置开始遍历,直到指定位置

  • shuffle()

             

                   shuffle()方法一样对链表采用了特殊策略,当链表长度大于SHUFFLE_THRESHOLD(设置为5)时,会先把链表转换为数组,然后再洗牌。

    洗牌用了随机数。

<think>我们首先介绍Java中的Collections类。Collections是Java集合框架中的一个工具类,位于java.util包下。它提供了一系列静态方法,用于对集合(如List、Set、Map等)进行操作,包括排序、搜索、同步化、不可变集合创建等。主要功能包括:1.排序(sort)2.混排(shuffle)3.反转(reverse)4.填充(fill)5.复制(copy)6.查找极值(min,max)7.二分查找(binarySearch)8.创建不可变集合(unmodifiableXXX)9.创建同步集合(synchronizedXXX)10.创建检查类型集合(checkedXXX)下面我们通过代码示例来展示Collections类的常用方法。###1.排序(sort)对List集合进行自然排序(升序)或使用自定义比较器排序。```javaimportjava.util.*;publicclassCollectionsDemo{publicstaticvoidmain(String[]args){List<Integer>list=newArrayList<>();list.add(5);list.add(2);list.add(8);list.add(1);//自然排序(升序)Collections.sort(list);System.out.println("升序排序:"+list);//[1,2,5,8]//使用自定义比较器(降序)Collections.sort(list,Collections.reverseOrder());System.out.println("降序排序:"+list);//[8,5,2,1]}}```###2.混排(shuffle)随机打乱List中元素的顺序。```javaCollections.shuffle(list);System.out.println("混排后:"+list);//每次运行结果不同```###3.反转(reverse)反转List中元素的顺序。```javaCollections.reverse(list);System.out.println("反转后:"+list);//[1,2,5,8]反转后变成[8,5,2,1]```###4.填充(fill)用指定元素替换List中的所有元素。```javaCollections.fill(list,0);System.out.println("填充0后:"+list);//[0,0,0,0]```###5.复制(copy)将源List中的元素复制到目标List中,目标List的大小必须大于等于源List。```javaList<Integer>src=Arrays.asList(1,2,3);List<Integer>dest=newArrayList<>(Arrays.asList(4,5,6,7));Collections.copy(dest,src);//将src复制到dest,覆盖dest的前三个元素System.out.println("复制后dest:"+dest);//[1,2,3,7]```###6.查找极值(min,max)根据自然顺序或自定义比较器查找最小值和最大值。```javaIntegermin=Collections.min(list);Integermax=Collections.max(list);System.out.println("最小值:"+min+",最大值:"+max);```###7.二分查找(binarySearch)在已排序的List中使用二分查找算法查找指定元素,返回索引(如果找到)。如果未找到,返回负值。```javaCollections.sort(list);//先排序intindex=Collections.binarySearch(list,2);System.out.println("元素2的索引:"+index);//1```###8.创建不可变集合(unmodifiableXXX)返回指定集合的不可变视图,任何修改操作都会抛出UnsupportedOperationException。```javaList<Integer>unmodifiableList=Collections.unmodifiableList(list);//unmodifiableList.add(10);//抛出UnsupportedOperationException```###9.创建同步集合(synchronizedXXX)返回指定集合的同步(线程安全)版本。```javaList<Integer>synchronizedList=Collections.synchronizedList(list);//在多线程环境中安全操作```###10.创建检查类型集合(checkedXXX)返回指定集合的动态类型安全视图,在运行时确保插入的元素类型正确。```javaList<Integer>checkedList=Collections.checkedList(list,Integer.class);//checkedList.add("abc");//在运行时抛出ClassCastException```###注意事项:-Collections类的方法都是静态方法,可以直接通过类名调用。-对于排序和二分查找,List中的元素必须实现Comparable接口,或者提供Comparator。-同步集合是通过在方法上添加synchronized块来实现的,因此在多线程环境中,对集合的迭代操作仍然需要手动同步。通过使用Collections工具类,我们可以方便地对集合进行各种操作,提高开发效率。§§相关问题§§:1.Java中Collections和Collection有什么区别?2.如何使用Collections类对自定义对象列表进行排序?3.Collections.synchronizedList和Vector有什么区别?4.如何利用Collections类实现一个线程安全的Map?</think>### Java中Collections类的介绍 `java.util.Collections`是Java集合框架中的一个**工具类**,提供了一系列**静态方法**用于操作或返回集合(如List、Set、Map)。这些方法主要分为以下几类: #### 1. 排序操作 ```java // 自然排序(升序) Collections.sort(list); // 自定义排序(实现Comparator) Collections.sort(list, (a, b) -> b.compareTo(a)); // 降序 ``` #### 2. 查找与极值 ```java // 二分查找(必须先排序) int index = Collections.binarySearch(sortedList, key); // 获取最小/最大值 Object min = Collections.min(collection); Object max = Collections.max(collection); ``` #### 3. 同步包装(线程安全) ```java List<String> syncList = Collections.synchronizedList(new ArrayList<>()); Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>()); ``` #### 4. 不可变集合 ```java List<String> unmodifiable = Collections.unmodifiableList(originalList); Set<Integer> singleton = Collections.singleton(42); // 单元素集合 ``` #### 5. 特殊操作 ```java Collections.reverse(list); // 反转顺序 Collections.shuffle(list); // 随机打乱 Collections.swap(list, i, j); // 交换元素 Collections.fill(list, "默认值"); // 填充相同值 ``` #### 6. 类型安全检查 ```java List<Integer> checkedList = Collections.checkedList(rawList, Integer.class); // 防止类型污染 ``` ### 完整示例代码 ```java import java.util.*; public class CollectionsDemo { public static void main(String[] args) { // 创建可修改列表 List<Integer> numbers = new ArrayList<>(Arrays.asList(3, 1, 4, 2)); // 排序操作 Collections.sort(numbers); // [1, 2, 3, 4] Collections.reverse(numbers); // [4, 3, 2, 1] // 创建不可变视图 List<Integer> immutable = Collections.unmodifiableList(numbers); // immutable.add(5); // 抛出UnsupportedOperationException // 线程安全包装 List<Integer> safeList = Collections.synchronizedList(numbers); // 特殊操作 Collections.swap(numbers, 0, 3); // [1, 3, 2, 4] int max = Collections.max(numbers); // 4 // 二分查找(需先排序) Collections.sort(numbers); int pos = Collections.binarySearch(numbers, 3); // 索引2 System.out.println("最终列表: " + numbers); } } ``` ### 关键特性说明: 1. **静态工具方法**:所有方法都是静态的,无需创建实例 2. **算法封装**:提供通用算法实现(排序/查找等) 3. **视图包装**:`unmodifiableXXX`/`synchronizedXXX`返回原集合的包装视图 4. **空集合支持**:`emptyList()`/`emptySet()`等返回不可变的空集合 5. **单例集合**:`singleton()`/`singletonList()`创建单元素集合 ### 使用注意事项: - 排序方法要求元素实现`Comparable`或提供`Comparator` - 二分查找**必须**在排序后使用 - 同步包装器仅保证单个操作的原子性,复合操作仍需额外同步 - 不可变视图会随原集合变化而变化(是"视图"而非副本)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值