Collections类提供了一些列静态的方法,用以更方便地操作集合类

排序机制

一个List可以通过下面的方法进行排序:

Collections.sort(list);

如果List包含的是字符串,将会按照字母表排序;如果List包含的是Date类型数据,会按照日期先后排序……这是怎么实现的呢?String和Date都实现了comparable接口,此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo 方法被称为它的自然比较方法

实现此接口的对象列表(和数组)可以通过Collections.sort(和 Arrays.sort)进行自动排序。实现此接口的对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。

对于类 C 的每一个 e1 和 e2 来说,当且仅当e1.compareTo(e2) == 0 与e1.equals(e2) 具有相同的 boolean值时,类 C 的自然排序才叫做与 equals 一致。注意,null 不是任何类的实例,即使e.equals(null) 返回 false,e.compareTo(null) 也将抛出 NullPointerException。

建议(虽然不是必需的)最好使自然排序与equals 一致。这是因为在使用自然排序与 equals 不一致的元素(或键)时,没有显式比较器的有序集合(和有序映射表)行为表现“怪异”。尤其是,这样的有序集合(或有序映射表)违背了根据 equals 方法定义的集合(或映射表)的常规协定。

例如,如果将两个键 a 和 b 添加到没有使用显式比较器的有序集合中,使 (!a.equals(b) && a.compareTo(b) == 0),那么第二个 add 操作将返回 false(有序集合的大小没有增加),因为从有序集合的角度来看,a 和 b 是相等的。

实际上,所有实现 Comparable 的 Java 核心类都具有与equals 一致的自然排序。java.math.BigDecimal 是个例外,它的自然排序将值相等但精确度不同的 BigDecimal 对象(比如 4.0 和 4.00)视为相等。

如果试图对一个没有实现comparable接口的类进行排序,会抛出ClassCastException

Comparable接口包含下面的方法:

public interface Comparable<T> {
    public int compareTo(T o);
}

compareTo方法比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。

实现类必须确保对于所有的 x 和 y 都存在sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) 的关系。(这意味着如果 y.compareTo(x)抛出一个异常,则 x.compareTo(y) 也要抛出一个异常。)

实现类还必须确保关系是可传递的:(x.compareTo(y)>0&& y.compareTo(z)>0) 意味着 x.compareTo(z)>0。

最后,实现者必须确保x.compareTo(y)==0 意味着对于所有的 z,都存在 sgn(x.compareTo(z)) == sgn(y.compareTo(z))。 强烈推荐(x.compareTo(y)==0) == (x.equals(y)) 这种做法,但并不是严格要求这样做。

在前面的描述中,符号sgn(expression) 指定 signum 数学函数,该函数根据 expression 的值是负数、零还是正数,分别返回 -1、0 或 1 中的一个值。

下面来看一个实例:

public class Name implements Comparable<Name> {
    private final String firstName, lastName;

    public Name(String firstName, StringlastName) {
        if (firstName == null || lastName ==null)
            throw new NullPointerException();
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String firstName() { return firstName;}
    public String lastName()  { return lastName;  }

       //覆写equals方法
    public boolean equals(Object o) {
        if (!(o instanceof Name))
            return false;
        Name n = (Name) o;
        return n.firstName.equals(firstName)&& n.lastName.equals(lastName);
    }

       //覆写了equals方法则必须覆写hashCode方法,相同的类必须有相同的哈希码
    public int hashCode(){
        return 31*firstName.hashCode() +lastName.hashCode();
    }

    public String toString() {
      return firstName + " " + lastName;
    }

       //当姓氏和名字都一样时,才认为该类相同
    public int compareTo(Name n) {
        int lastCmp =lastName.compareTo(n.lastName);
              //先比较姓氏,如果姓氏相同,再比较名字
        return (lastCmp != 0 ? lastCmp :firstName.compareTo(n.firstName));
    }
}

测试类
Name nameArray []= {
                         new Name("John","Smith"),
                         new Name("Karl","Ng"),
                         new Name("Jeff","Smith"),
                         new Name("Tom","Rich")
                   };

                     List<Name> names =Arrays.asList(nameArray);
                     Collections.sort(names);
                     System.out.println(names);

输出:

[Karl Ng, TomRich, Jeff Smith, John Smith]

如果我们不想按照自然排序,而是希望以一种特殊的方式排序呢?这是就需要提供一个Comparator。跟Comparable接口一样,该接口也只包含一个方法:

public interface Comparator<T> {
    int compare(T o1, T o2);
}

Comparator提供了强行对某个对象collection 进行整体排序的比较函数。可以将 Comparator传递给 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的顺序,或者为那些没有自然顺序的对象 collection 提供排序。

当使用具有与 equals 不一致的强行排序能力的Comparator 对有序 set(或有序映射)进行排序时,应该小心谨慎。假定一个带显式 Comparator c 的有序 set(或有序映射)与从 set S 中抽取出来的元素(或键)一起使用。如果 c 强行对 S 进行的排序是与 equals 不一致的,那么有序 set(或有序映射)将是行为“怪异的”。尤其是有序 set(或有序映射)将违背根据 equals 所定义的 set(或映射)的常规协定。

例如,假定使用 Comparator c 将满足(a.equals(b) && c.compare(a, b) != 0) 的两个元素 a 和 b 添加到一个空TreeSet 中,则第二个 add 操作将返回 true(树 set 的大小将会增加),因为从树 set 的角度来看,a 和 b 是不相等的,即使这与 Set.add 方法的规范相反。

来看一个实例:

public class Employee implements Comparable<Employee> {
    public Name name()     { ... }
    public int number()    { ... }
    public Date hireDate() { ... }
       ...
}

员工类包含员工的姓名、工号、入职日期等属性,并且实现了Comparable接口,它的自然排序是按照Name来排序的(具体代码见上面的Name类)。假如现在我们不想让它按照Name来排序,而是按照入职日期来排序,利用Comparator来实现:

  static final Comparator<Employee> SENIORITY_ORDER =
                                        new Comparator<Employee>() {
            public int compare(Employee e1,Employee e2) {
                             //根据入职日期进行排序,本质上还是利用了Date类型的compareTo方法
                return e2.hireDate().compareTo(e1.hireDate());
            }
    };

    // Employee database
    static final Collection<Employee>employees = ... ;

    public static void main(String[] args) {
        List<Employee> e = new ArrayList<Employee>(employees);
        Collections.sort(e, SENIORITY_ORDER);  //传入指定的比较器
        System.out.println(e);
    }

同步“包装”机制

通用的集合类都是线程不安全的,如果需要线程安全的集合类,可以通过Collections类的包装对它们进行转换。

六个核心的接口都有一个静态的工厂方法:

public static <T> Collection<T>synchronizedCollection(Collection<T> c);

public static <T> Set<T> synchronizedSet(Set<T>s);

public static <T> List<T> synchronizedList(List<T>list);

public static <K,V> Map<K,V>synchronizedMap(Map<K,V> m);

public static <T> SortedSet<T>synchronizedSortedSet(SortedSet<T> s);

public static <K,V> SortedMap<K,V>synchronizedSortedMap(SortedMap<K,V> m);

例如,通过下面的这行语句:

List<Type>list = Collections.synchronizedList(new ArrayList<Type>());

我们就得到了一个线程安全的List

在多线程的情况下,使用者在进行迭代的时候需要注意集合的同步状态,推荐的做法是这样:

Collection<Type> c = Collections.synchronizedCollection(myCollection);
synchronized(c){
    for (Type e : c)
        foo(e);
}

如果使用的是显式迭代器,Iterator方法必须在同步快中调用。对Map的视图进行迭代时也是同样的要求。

Map<KeyType,ValType> m = Collections.synchronizedMap(new HashMap<KeyType,ValType>());
    ...
Set<KeyType> s = m.keySet();
    ...
// Synchronizingon m, not s!
synchronized(m){
    while (KeyType k : s)
        foo(k);
}

方法列表

static <T>boolean addAll(Collection<? superT> c, T... elements)

将所有指定元素添加到指定collection 中。

static <T>int binarySearch(List<? extendsComparable<? super T>> list, T key)

使用二分搜索法搜索指定列表,以获得指定对象。

static <E>Collection<E>
checkedCollection
(Collection<E>c, Class<E> type)

返回指定 collection 的一个动态类型安全视图。

static <E>List<E> checkedList(List<E>list, Class<E> type)

返回指定列表的一个动态类型安全视图。

static<K,V> Map<K,V> checkedMap(Map<K,V>m, Class<K> keyType, Class<V> valueType)

返回指定映射的一个动态类型安全视图。

static <E>Set<E> checkedSet(Set<E>s, Class<E> type)

返回指定 set 的一个动态类型安全视图。

static<K,V> SortedMap<K,V>
checkedSortedMap
(SortedMap<K,V>m, Class<K> keyType, Class<V> valueType)

返回指定有序映射的一个动态类型安全视图。

static <E>SortedSet<E>
checkedSortedSet
(SortedSet<E>s, Class<E> type)

返回指定有序 set 的一个动态类型安全视图。

static <T>void copy(List<? super T>dest, List<? extends T> src)

将所有元素从一个列表复制到另一个列表。

static boolean disjoint(Collection<?> c1,Collection<?> c2)

如果两个指定 collection 中没有相同的元素,则返回true。

static <T>List<T> emptyList()

返回空的列表(不可变的)。

static<K,V> Map<K,V> emptyMap()

返回空的映射(不可变的)。

static <T>Set<T> emptySet()

返回空的 set(不可变的)。

static <T>Enumeration<T>
enumeration
(Collection<T>c)

返回一个指定 collection 上的枚举。

static <T>void fill(List<? super T>list, T obj)

使用指定元素替换指定列表中的所有元素。

static int frequency(Collection<?> c, Objecto)

返回指定 collection 中等于指定对象的元素数。

static int indexOfSubList(List<?> source,List<?> target)

返回指定源列表中第一次出现指定目标列表的起始位置;如果没有出现这样的列表,则返回 -1。

static int lastIndexOfSubList(List<?>source, List<?> target)

返回指定源列表中最后一次出现指定目标列表的起始位置;如果没有出现这样的列表,则返回 -1。

static <T>ArrayList<T>
list
(Enumeration<T>e)

返回一个数组列表,它按返回顺序包含指定枚举返回的元素。

static <Textends Object & Comparable<? super T>> T max(Collection<?extends T> coll)

根据元素的自然顺序,返回给定collection 的最大元素。

static <Textends Object & Comparable<? super T>> Tmin(Collection<? extends T> coll)

根据元素的自然顺序 返回给定 collection 的最小元素。

static <T>List<T>  nCopies(int n, T o)

返回由指定对象的 n 个副本组成的不可变列表。

static <T>boolean  replaceAll(List<T> list, T oldVal, T newVal)

使用另一个值替换列表中出现的所有某一指定值。

static void reverse(List<?> list)

反转指定列表中元素的顺序。

static void rotate(List<?> list, int distance)

根据指定的距离轮换指定列表中的元素。

static void shuffle(List<?> list)

使用默认随机源对指定列表进行置换。

static <T>Set<T> singleton(T o)

返回一个只包含指定对象的不可变 set。

static <T>List<T> singletonList(T o)

返回一个只包含指定对象的不可变列表。

static<K,V> Map<K,V> singletonMap(Kkey, V value)

返回一个不可变的映射,它只将指定键映射到指定值。

static <Textends Comparable<? super T>> voidsort(List<T> list)

根据元素的自然顺序 对指定列表按升序进行排序。

static void swap(List<?> list, int i, int j)

在指定列表的指定位置处交换元素。

static <T>Collection<T>
synchronizedCollection
(Collection<T>c)

返回指定 collection 支持的同步(线程安全的)collection。

static <T>List<T> synchronizedList(List<T>list)

返回指定列表支持的同步(线程安全的)列表。

static<K,V> Map<K,V> synchronizedMap(Map<K,V>m)

返回由指定映射支持的同步(线程安全的)映射。

static <T>Set<T> synchronizedSet(Set<T>s)

返回指定 set 支持的同步(线程安全的)set。

static<K,V> SortedMap<K,V>
synchronizedSortedMap
(SortedMap<K,V>m)

返回指定有序映射支持的同步(线程安全的)有序映射。

static <T>SortedSet<T>
synchronizedSortedSet
(SortedSet<T>s)

返回指定有序 set 支持的同步(线程安全的)有序 set。

static <T>Collection<T>
unmodifiableCollection
(Collection<?extends T> c)

返回指定 collection 的不可修改视图。

static <T>List<T> unmodifiableList(List<?extends T> list)

返回指定列表的不可修改视图。

static<K,V> Map<K,V> unmodifiableMap(Map<?extends K,? extends V> m)

返回指定映射的不可修改视图。

static <T>Set<T> unmodifiableSet(Set<?extends T> s)

返回指定 set 的不可修改视图。

static<K,V> SortedMap<K,V>
unmodifiableSortedMap
(SortedMap<K,?extends V> m)

返回指定有序映射的不可修改视图。

static <T>SortedSet<T>
unmodifiableSortedSet
(SortedSet<T>s)

返回指定有序 set 的不可修改视图。

集合框架之Collections静态工具类的更多相关文章

  1. java内部类、接口、集合框架、泛型、工具类、实现类

    .t1 { background-color: #ff8080; width: 1100px; height: 40px } 一.内部类 1.成员内部类. (1)成员内部类的实例化: 外部类名.内部类 ...

  2. Java集合框架GS Collections具体解释

    Java集合框架GS Collections具体解释 作者:chszs.未经博主同意不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs GS Collec ...

  3. java基础课程笔记 static 主函数 静态工具类 classpath java文档注释 静态代码块 对象初始化过程 设计模式 继承 子父类中的函数 继承中的构造函数 对象转型 多态 封装 抽象类 final 接口 包 jar包

    Static那些事儿 Static关键字 被static修饰的变量成为静态变量(类变量) 作用:是一个修饰符,用于修饰成员(成员变量,成员方法) 1.被static修饰后的成员变量只有一份 2.当成员 ...

  4. Java集合框架:Collections工具类

    java.util.Collections工具类提供非常多实用的方法.使得程序员操作集合类的时候更加的方便easy,这些方法都是静态的. 整个Collections工具类源代码几乎相同有4000行.我 ...

  5. JDK1.6新特性,基础类库篇,集合框架(Collections)

    2006 年底,Sun 公司发布了 Java Standard Edition 6(Java SE 6)的最终正式版,代号 Mustang(野马). 集合框架增强如下: 1. 增加了如下新接口(Int ...

  6. JDK1.5新特性,基础类库篇,集合框架(Collections)

    集合框架在JDK1.5中增强特性如下: 一. 新语言特性的增强 泛型(Generics)- 增加了集合框架在编译时段的元素类型检查,节省了遍历元素时类型转换代码量. For-Loop循环(Enhanc ...

  7. java集合框架之Collections

    参考http://how2j.cn/k/collection/collection-collections/369.html Collections是一个类,容器的工具类,就如同Arrays是数组的工 ...

  8. 57 容器(十一)——Collections容器工具类

    Collections是一个工具类,它提供了与集合操作有关的方法,好比数组中的Arrays工具类.(jdk中的工具类名都是xxxs,有关工具类名参考:https://zhuanlan.zhihu.co ...

  9. spring 在静态工具类中使用注解注入bean

    /** * @author: jerry * @Email: * @Company: * @Action: 日志处理工具类 * @DATE: 2016-9-19 */ @Component//泛指组件 ...

随机推荐

  1. TF-IDF In Scikit-Learn

    TF-IDF In Scikit-Learn 2017年9月30日补充   其实在算下面TF-IDF的步骤之前,还有一步,就是计算Term Frequency 也就是词频.当然,scikit-lear ...

  2. USACO 2017 February Platinum

    第二次参加USACO 本来打算2016-2017全勤的 January的好像忘记打了 听群里有人讨论才想起来铂金组三题很有意思,都是两个排列的交叉对问题 我最后得分889/1000(真的菜) T1.W ...

  3. BZOJ4589 Hard Nim(快速沃尔什变换模板)

    终于抽出时间来学了学,比FFT不知道好写到哪里去. #include <cstdio> typedef long long ll; ,p=1e9+; int k,m,n,a[N],pi[N ...

  4. SpringCloud学习之sleuth&zipkin【二】

    这篇文章我们解决上篇链路跟踪的遗留问题 一.将追踪数据存放到MySQL数据库中 默认情况下zipkin将收集到的数据存放在内存中(In-Memeroy),但是不可避免带来了几个问题: 在服务重新启动后 ...

  5. Machine Learning From Scratch-从头开始机器学习

    Python implementations of some of the fundamental Machine Learning models and algorithms from scratc ...

  6. [ 学习笔记 ] Hibernate框架学习之一

    一.JavaEE开发三层结构和三大框架的对应关系: Struts2框架 -> 表现层 web层(MVC是表现层的设计模型) 业务层 service层 Hibernate框架 -> 持久层 ...

  7. laravel实现支付宝支付功能

    起因 前段时间因为项目中需要实现支付宝手机网站支付功能,所以写下这篇文章以作记录,不足之处,欢迎指教. 后端框架:Laravel 5.5 业务功能 适用于商家在移动端网页应用中集成支付宝支付功能.商家 ...

  8. Tomcat和JDK的内存配置

    1.jvm内存管理机制: 1)堆(Heap)和非堆(Non-heap)内存 按照官方的说法:"Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Ja ...

  9. SQL注入原理及绕过安全狗

    1.什么是SQL注入攻击 SQL注入攻击指的是通过构造特殊的输入作为参数插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令 http://www.xxx.com/list. ...

  10. 独立完成一个移动点餐wap后的小结

    1.技术栈:vue  vue-router  vuex  Mint-ui  better-scroll; 2.实践总结: a.单页应用不重新渲染组件问题:组件在初次渲染后不会重新渲染,此时当从某个路径 ...