操作集合的工具类Collections

本文详细介绍了Java中Collections工具类的功能,包括对List、Set和Map集合的操作,如排序、查询、修改、同步控制及不可变集合的设置。通过实例展示了如何使用Collections类的方法进行集合元素的排序、查找、替换等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

Java提供了一个操作Set、List和Map等集合的工具类:Collections,该工具类里提供了大量方法对集合元素进行排序、查询和修改等操作,还提供了将集合对象设置为不可变、对集合对象实现同步控制等方法。

排序操作

Collections提供了如下几个方法用于对List集合元素进行排序。

反转指定List集合中元素的顺序

    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);
            }
        }
    }

对List集合元素进行随机排序(shuffle方法模拟了洗牌动作)

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

根据元素的自然顺序对指定List集合的元素按升序进行排序

    public static <T extends Comparable<? super T>> void sort(List<T> list) {
        list.sort(null);
    }

根据指定Comparator产生的顺序对List集合元素进行排序

    public static <T> void sort(List<T> list, Comparator<? super T> c) {
        list.sort(c);
    }

将指定List集合中的i处元素和j处元素进行交换

    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)));
    }

当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);
    }
public class SortTest {

    public static void main(String[] args) {
        ArrayList nums = new ArrayList();

        nums.add(2);
        nums.add(-5);
        nums.add(3);
        nums.add(0);

        System.out.println(nums);
        //将List集合元素的次序反转
        Collections.reverse(nums);
        System.out.println(nums);

        //将List集合元素按自然顺序排序
        Collections.sort(nums);
        System.out.println(nums);

        //将List集合元素按随机顺序排序
        Collections.shuffle(nums);
        //每次输出的次序不固定
        System.out.println(nums);


    }

}
[2, -5, 3, 0]
[0, 3, -5, 2]
[-5, 0, 2, 3]
[-5, 3, 0, 2]

查找、替换操作

Collections还提供了如下用于查找、替换集合元素的常用方法。

使用二分搜索法搜索指定的List集合,以获得指定对象在List集合中的索引。如果要使用该方法可以正常工作,则必须保证List中的元素已经处于有序状态

    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);
    }

根据元素的自然顺序,返回给定集合中的最大元素

    public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
        Iterator<? extends T> i = coll.iterator();
        T candidate = i.next();

        while (i.hasNext()) {
            T next = i.next();
            if (next.compareTo(candidate) > 0)
                candidate = next;
        }
        return candidate;
    }

根据Comparator指定的顺序,返回给定集合中的最大元素

    public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp) {
        if (comp==null)
            return (T)max((Collection) coll);

        Iterator<? extends T> i = coll.iterator();
        T candidate = i.next();

        while (i.hasNext()) {
            T next = i.next();
            if (comp.compare(next, candidate) > 0)
                candidate = next;
        }
        return candidate;
    }

根据元素的自然顺序,返回给定集合中的最小元素

    public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll) {
        Iterator<? extends T> i = coll.iterator();
        T candidate = i.next();

        while (i.hasNext()) {
            T next = i.next();
            if (next.compareTo(candidate) < 0)
                candidate = next;
        }
        return candidate;
    }

根据Comparator指定的顺序,返回给定集合中的最小元素

    public static <T> T min(Collection<? extends T> coll, Comparator<? super T> comp) {
        if (comp==null)
            return (T)min((Collection) coll);

        Iterator<? extends T> i = coll.iterator();
        T candidate = i.next();

        while (i.hasNext()) {
            T next = i.next();
            if (comp.compare(next, candidate) < 0)
                candidate = next;
        }
        return candidate;
    }

使用指定元素obj替换指定List集合中的所有元素

    public static <T> void fill(List<? super T> list, T obj) {
        int size = list.size();

        if (size < FILL_THRESHOLD || list instanceof RandomAccess) {
            for (int i=0; i<size; i++)
                list.set(i, obj);
        } else {
            ListIterator<? super T> itr = list.listIterator();
            for (int i=0; i<size; i++) {
                itr.next();
                itr.set(obj);
            }
        }
    }

返回指定集合中指定元素的出现次数

    public static int frequency(Collection<?> c, Object o) {
        int result = 0;
        if (o == null) {
            for (Object e : c)
                if (e == null)
                    result++;
        } else {
            for (Object e : c)
                if (o.equals(e))
                    result++;
        }
        return result;
    }

返回子List对象在父List对象中第一次出现的位置索引;如果父List中没有出现这样的子List,则返回-1

    public static int indexOfSubList(List<?> source, List<?> target) {
        int sourceSize = source.size();
        int targetSize = target.size();
        int maxCandidate = sourceSize - targetSize;

        if (sourceSize < INDEXOFSUBLIST_THRESHOLD ||
            (source instanceof RandomAccess&&target instanceof RandomAccess)) {
        nextCand:
            for (int candidate = 0; candidate <= maxCandidate; candidate++) {
                for (int i=0, j=candidate; i<targetSize; i++, j++)
                    if (!eq(target.get(i), source.get(j)))
                        continue nextCand;  // Element mismatch, try next cand
                return candidate;  // All elements of candidate matched target
            }
        } else {  // Iterator version of above algorithm
            ListIterator<?> si = source.listIterator();
        nextCand:
            for (int candidate = 0; candidate <= maxCandidate; candidate++) {
                ListIterator<?> ti = target.listIterator();
                for (int i=0; i<targetSize; i++) {
                    if (!eq(ti.next(), si.next())) {
                        // Back up source iterator to next candidate
                        for (int j=0; j<i; j++)
                            si.previous();
                        continue nextCand;
                    }
                }
                return candidate;
            }
        }
        return -1;  // No candidate matched the target
    }

返回子List对象在父List对象中最后一次出现的位置索引;如果父List中没有出现这样的子List,则返回-1

    public static int lastIndexOfSubList(List<?> source, List<?> target) {
        int sourceSize = source.size();
        int targetSize = target.size();
        int maxCandidate = sourceSize - targetSize;

        if (sourceSize < INDEXOFSUBLIST_THRESHOLD ||
            source instanceof RandomAccess) {   // Index access version
        nextCand:
            for (int candidate = maxCandidate; candidate >= 0; candidate--) {
                for (int i=0, j=candidate; i<targetSize; i++, j++)
                    if (!eq(target.get(i), source.get(j)))
                        continue nextCand;  // Element mismatch, try next cand
                return candidate;  // All elements of candidate matched target
            }
        } else {  // Iterator version of above algorithm
            if (maxCandidate < 0)
                return -1;
            ListIterator<?> si = source.listIterator(maxCandidate);
        nextCand:
            for (int candidate = maxCandidate; candidate >= 0; candidate--) {
                ListIterator<?> ti = target.listIterator();
                for (int i=0; i<targetSize; i++) {
                    if (!eq(ti.next(), si.next())) {
                        if (candidate != 0) {
                            // Back up source iterator to next candidate
                            for (int j=0; j<=i+1; j++)
                                si.previous();
                        }
                        continue nextCand;
                    }
                }
                return candidate;
            }
        }
        return -1;  // No candidate matched the target
    }

使用一个新值newVal替换List对象的所有旧值oldVal

    public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal) {
        boolean result = false;
        int size = list.size();
        if (size < REPLACEALL_THRESHOLD || list instanceof RandomAccess) {
            if (oldVal==null) {
                for (int i=0; i<size; i++) {
                    if (list.get(i)==null) {
                        list.set(i, newVal);
                        result = true;
                    }
                }
            } else {
                for (int i=0; i<size; i++) {
                    if (oldVal.equals(list.get(i))) {
                        list.set(i, newVal);
                        result = true;
                    }
                }
            }
        } else {
            ListIterator<T> itr=list.listIterator();
            if (oldVal==null) {
                for (int i=0; i<size; i++) {
                    if (itr.next()==null) {
                        itr.set(newVal);
                        result = true;
                    }
                }
            } else {
                for (int i=0; i<size; i++) {
                    if (oldVal.equals(itr.next())) {
                        itr.set(newVal);
                        result = true;
                    }
                }
            }
        }
        return result;
    }
代码演示
public class SearchTest {

    public static void main(String[] args) {
        ArrayList nums = new ArrayList();

        nums.add(2);
        nums.add(-5);
        nums.add(3);
        nums.add(0);

        System.out.println(nums);

        //输出最大元素,将输出3
        System.out.println(Collections.max(nums));
        //输出最小元素,将输出-5
        System.out.println(Collections.min(nums));
        //将nums中的0使用1来替代
        Collections.replaceAll(nums, 0, 1);
        System.out.println(nums);

        //判断-5在List集合中出现的次数
        System.out.println(Collections.frequency(nums, -5));

        //对nums集合排序
        Collections.sort(nums);
        System.out.println(nums);

        //只有排序后的List集合才可用二分法查询
        System.out.println(Collections.binarySearch(nums, 3));





    }

}
输出结果
[2, -5, 3, 0]
3
-5
[2, -5, 3, 1]
1
[-5, 1, 2, 3]
3

同步控制

Collections类中提供了多个synchronizedXxx()方法,该方法可以将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题。

public class SynchronizedTest {
    public static void main(String[] args) {
        //下面程序创建了4个同步的集合对象
        Collection c = Collections.synchronizedCollection(new ArrayList<>());
        
        List list = Collections.synchronizedList(new ArrayList<>());

        Set s = Collections.synchronizedSet(new HashSet<>());
        
        Map m = Collections.synchronizedMap(new HashMap<>());
        
    }
}

设置不可变集合

Collections提供了如下三个方法来返回一个不可变的集合。

emptyXxx()

返回一个空的、不可变的集合对象,此处的集合可以是List、Set、Map

singletonXxx()

返回一个只包含指定对象(只有一个或一项元素)的、不可变的集合对象,此处的集合可以是List、Set、Map

unmodifiableXxx()

返回指定集合对象的不可变视图,此处的集合可以是List、Set、Map

上面三类方法的参数是原有的集合对象,返回值是该集合的只读版本。

public class UnmodifiableTest {

    public static void main(String[] args) {
        //创建一个空的,不可改变的List对象
        List unmodifiableList = Collections.emptyList();

        //创建一个只有一个元素,且不可改变的Set对象
        Set unmodifiableSet = Collections.singleton("疯狂Java讲义");

        //创建一个普通的Map对象
        Map scores = new HashMap<>();
        scores.put("语文", 80);
        scores.put("Java", 82);

        //返回普通的Map对象对应的不可变版本
        Map unmodifiableMap = Collections.unmodifiableMap(scores);

        //以下任意一行代码都将引发不支持操作异常
        unmodifiableList.add("测试元素");
        unmodifiableSet.add("测试元素");
        unmodifiableMap.put("语文", 90);


    }

}

不可变的集合对象只能访问集合元素,不可修改集合元素

繁琐的接口:Enumeration

Enumeration接口是Iterator迭代器的古老版本,从JDK1.0开始,Enumeration接口就已经存在了(Iterator从JDK1.2才出现)。

如果现在编写Java程序,应该尽量采用Iterator迭代器,而不是用Enumeration迭代器

Java之所以保留Enumeration接口,主要是为了照顾以前那些“古老”的程序,那些程序里大量使用了Enumeration接口,如果新版本的Java里直接删除Enumeration接口,将会导致那些程序全部出错。在计算机行业有一条规则:加入任何规则都必须慎之又慎,因为以后无法删除规则。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值