美文网首页
Collection和Collections的区别

Collection和Collections的区别

作者: 小沙鹰168 | 来源:发表于2017-04-28 12:42 被阅读0次

    1、java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。
    Collection
    ├List
    │├LinkedList
    │├ArrayList
    │└Vector
    │ └Stack
    └Set

    Collection.png

    1、Collection接口
    Collection是最基本集合接口,它定义了一组允许重复的对象。Collection接口派生了两个子接口Set和List,分别定义了两种不同的存储方式,如下:

    2、 Set接口
    Set接口继承于Collection接口,它没有提供额外的方法,但实现了Set接口的集合类中的元素是无序且不可重复。
    特征:无序且不可重复。

    3、 List接口
    List接口同样也继承于Collection接口,但是与Set接口恰恰相反,List接口的集合类中的元素是对象有序且可重复。
    特征:有序且可重复。
    两个重要的实现类:ArrayList和LinkedList
    1.ArrayList特点是有序可重复的
    2.LinkedList是一个双向链表结构的。

    4、Map接口
    Map也是接口,但没有继承Collection接口。该接口描述了从不重复的键到值的映射。Map接口用于维护键/值对(key/value pairs)。
    特征:它描述了从不重复的键到值的映射。
    两个重要的实现类:HashMap和TreeMap
    1.HashMap,中文叫散列表,基于哈希表实现,特点就是键值对的映射关系。一个key对应一个Value。HashMap中元素的排列顺序是不固定的。更加适合于对元素进行插入、删除和定位。
    2.TreeMap,基于红黑书实现。TreeMap中的元素保持着某种固定的顺序。更加适合于对元素的顺序遍历。

    5、Iterator接口
    Iterator接口,在C#里有例外一种说法IEnumerator,他们都是集合访问器,用于循环访问集合中的对象。 所有实现了Collection接口的容器类都有iterator方法,用于返回一个实现了Iterator接口的对象。Iterator对象称作迭代器,Iterator接口方法能以迭代方式逐个访问集合中各个元素,并可以从Collection中除去适当的元素。

    2、java.util.Collections 是一个包装类(工具类/帮助类)。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,用于对集合中元素进行排序、搜索以及线程安全等各种操作,服务于Java的Collection框架。

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
     
    public class TestCollections {
       
        public static void main(String args[]) {
            //注意List是实现Collection接口的
            List list = new ArrayList();
            double array[] = { 112, 111, 23, 456, 231 };
            for (int i = 0; i < array.length; i++) {
                list.add(new Double(array[i]));
            }
            Collections.sort(list);
            for (int i = 0; i < array.length; i++) {
                System.out.println(list.get(i));
            }
            // 结果:23.0 111.0 112.0 231.0 456.0
        }
    }
    

    Collections类里面包括动态、有序、可变大小的一维数组Vector与ArrayList。
    Vector与ArrayList,两者唯一的差别是:vector自带线程互斥,多个线程对其读写会抛出异常,而arraylist则允许多个线程读写,其他部分是一模一样的,换句话说,如果是单线程在读写,使用Vector与ArrayList没有任何区别,但现在编程基本都用ArrayList,使用Vector有点非主流了
    1、Vector的使用如下:

    public static void Vectortest() {
    // Vector<Double>表示这个vector只能存放double
    // Vector<String>表示这个vector只能存String
    // 虽然Vector<Object> vector=new Vector<Object>();等价于Vector vector=new
    // Vector();但是,eclipse中这样写会警告,表示你这个Vector不规范,╮(╯▽╰)╭
    Vector<Object> vector = new Vector<Object>();
    vector.add(1.6);
    vector.add(2.06);
    vector.add(1);
    System.out.println("单纯的add表示从结尾加入元素:" + vector);
    System.out.println("size()能求出vector的所含元素的个数:" + vector.size());
    vector.remove(1);
    System.out.println("remove(1)表示删去第1个元素,由于计数从0开始,也就是2.06这个元素:" + vector);
    vector.remove(vector.lastElement());
    System.out.println("删去最后一个元素的vector为:" + vector);
    vector.add(0, 1.8888);
    System.out.println("在第0个位置加入1.8888这个元素:" + vector);
    vector.set(0, "a");
    System.out.println("把第0个位置这个元素改为a:" + vector);
    }
    

    这段方法如果在主函数调用:

    System.out.println("======Vector数据结构的测试开始======");
     Vectortest();
    System.out.println("======Vector数据结构的测试结束======");
    

    运行结果如下:
    ======Vector数据结构的测试开始======
    单纯的add表示从结尾加入元素:[1.6, 2.06, 1]
    size()能求出vector的所含元素的个数:3
    remove(1)表示删去第1个元素,由于计数从0开始,也就是2.06这个元素:[1.6, 1]
    删去最后一个元素的vector为:[1.6]
    在第0个位置加入1.8888这个元素:[1.8888, 1.6]
    把第0个位置这个元素改为a:[a, 1.6]
    ======Vector数据结构的测试结束======

    2、ArrayList

    public static void ArrayListtest() {
    ArrayList<Double> arraylist = new ArrayList<Double>();
    arraylist.add(1.0);
    arraylist.add(4.0);
    arraylist.add(5.0);
    arraylist.add(2.3);
    System.out.println("单纯的add表示从结尾加入元素:" + arraylist);
    System.out.println("size()能求出所含元素的个数:" + arraylist.size());
    arraylist.remove(1);
    System.out.println("remove(1)表示删去第1个元素,由于计数从0开始,也就是4这个元素:" + arraylist);
    arraylist.remove(arraylist.size() - 1);
    System.out.println("删去最后一个元素的arraylist为:" + arraylist);
    arraylist.add(0, 1.8888);
    System.out.println("在第0个位置加入1.8888这个元素:" + arraylist);
    arraylist.set(0, 9.0);
    System.out.println("把第0个位置这个元素改为a:" + arraylist);
    Collections.sort(arraylist);
    System.out.println("如果arraylist不是抽象类型,则支持排序" + arraylist);
     
    }
    

    这里可以看到ArrayList删除最后一个元素的方式与Vector有所不同,主要是ArrayList没有lastElement()这个方法来取出最后一个元素remove()掉,只能用arraylist.size() - 1来确定最后一个元素的位置。如果在主函数这样调用这段方法:

    System.out.println("======ArrayList数据结构的测试开始======");
    ArrayListtest();
    System.out.println("======ArrayList数据结构的测试结束======");
    

    则得到如下的运行结果:
    ======ArrayList数据结构的测试开始======
    单纯的add表示从结尾加入元素:[1.0, 4.0, 5.0, 2.3]
    size()能求出所含元素的个数:4
    remove(1)表示删去第1个元素,由于计数从0开始,也就是4这个元素:[1.0, 5.0, 2.3]
    删去最后一个元素的arraylist为:[1.0, 5.0]
    在第0个位置加入1.8888这个元素:[1.8888, 1.0, 5.0]
    把第0个位置这个元素改为a:[9.0, 1.0, 5.0]
    如果arraylist不是抽象类型,则支持排序[1.0, 5.0, 9.0]
    ======ArrayList数据结构的测试结束======

    从上面的两个例子,可以看到Vector与ArrayList比一个普通的数组,也就是课本上所教的一维数组int array[] = { 8, 7, 100, 88, 6, 4, 5, 33, 7 };强大很多,可以在任意位置插入元素,也可以不用遍历数组就能够用一个方法删除指定位置的元素,当然为你考试你还是要知道这个数组是怎么遍历的。其实,ArrayList与普通的一维数组完全可以实现互转,而且利用ArrayList还能够直接对array进行排序,而不用再对array写一个冒泡排序之类的,直接用Collections.sort();就能够排序数组,然后再用Collections.reverse();就能实现逆排序,当然还是那句,为你考试你还是要知道这个数组是怎么排序的。
    比如如下的方法,实现了对一维数组int array[] = { 8, 7, 100, 88, 6, 4, 5, 33, 7 };的排序与逆排序,先把数组转化成ArrayList再用Collections.sort();与Collections.reverse();排序,最后再把ArrayList内容转化回一维数组:

    public static void arrayListSort() {
    int array[] = { 8, 7, 100, 88, 6, 4, 5, 33, 7 };
    ArrayList<Integer> arraylist = new ArrayList<Integer>();
    for (int i = 0; i < array.length; i++)
    System.out.print(array[i] + ",");
    for (int i = 0; i < array.length; i++)
    arraylist.add(array[i]);
    Collections.sort(arraylist);
    for (int i = 0; i < array.length; i++)
    array[i] = arraylist.get(i);
    System.out.print("排序后的数组:");
    for (int i = 0; i < array.length; i++)
    System.out.print(array[i] + ",");
    Collections.reverse(arraylist);
    for (int i = 0; i < array.length; i++)
    array[i] = arraylist.get(i);
    System.out.print("逆排序后的数组:");
    for (int i = 0; i < array.length; i++)
    System.out.print(array[i] + ",");
    //排序之后把arraylist销毁
    arraylist = null;
    //这句是建议Java马上回收垃圾,当然这句有没有都行,Java在运行的过程中会自动清除垃圾的
    System.gc();
    }
    

    在主函数中这样调用方法:

    System.out.println("======Java数组排序开始======");
    arrayListSort();
    System.out.println("======Java数组排序结束======");
    

    就能够得到如下的运行结果: ======Java数组排序开始====== 8,7,100,88,6,4,5,33,7,排序后的数组:4,5,6,7,7,8,33,88,100,逆排序后的数组:100,88,33,8,7,7,6,5,4, ======Java数组排序结束====== 另外,之前说的《Java中List的使用方法简单介绍》(点击打开链接)也是同样的道理 。
    二、集合HashSet
    另外,还有集合HashSet,HashSet与数学上的集合概念一模一样。由一个或多个元素所构成的叫做集合。HashSet具有:
    1.确定性,集合中的元素必须是确定的,这个是废话,必须确定,难道我还可以在里面放一个不确定的东西进去吗?
    2.互异性,集合中的元素互不相同。例如:集合A={1,a},则a不能等于1,也就是如果你把两个1放进HashSet会自动变为一个1
    3.无序性,集合中的元素没有先后之分。因此HashSet也不得进行排序操作
    例如如下的一段方法:

    public static void HashSettest() {
    HashSet<Object> hashset = new HashSet<Object>();
    hashset.add(1);
    hashset.add(1);
    hashset.add(5);
    hashset.add(2.3);
    System.out.println("单纯的add表示从结尾加入元素:" + hashset);
    System.out.println("size()能求出所含元素的个数:" + hashset.size());
    hashset.remove(1);
    System.out.println("remove(1)表示删去'1'这个元素:" + hashset);
    hashset.remove("asd");
    System.out.println("如果没有'asd'这个元素则remove什么都不做:" + hashset);
    hashset.add(1.8888);
    System.out.println("加入1.8888这个元素:" + hashset);
    }
    

    在主函数中,调用这个方法:

    System.out.println("======HashSet数据结构的测试开始======");
    HashSettest();
    System.out.println("======HashSet数据结构的测试结束======"); 
    

    结果如下:
    ======HashSet数据结构的测试开始======
    单纯的add表示从结尾加入元素:[1, 5, 2.3]
    size()能求出所含元素的个数:3
    remove(1)表示删去'1'这个元素:[5, 2.3]
    如果没有'asd'这个元素则remove什么都不做:[5, 2.3]
    加入1.8888这个元素:[5, 1.8888, 2.3]
    ======HashSet数据结构的测试结束======
    HashSet有add()方法与remove()方法,add()所加的元素没有顺序,每次用System.out.println()打印的结果可能顺序不一样,也不能向上面Vector与ArrayList一样,只要所存的元素不是Object,就能使用Collections.sort(arraylist);来排序

    三、二元组HashMap
    这里的使用方法和上面的数据基本相同,也很简单,就是put方法来对象进去map,而get能够取走map中的对象,但是试图把二元组HashMap用成三元组是错误的,如果一个对象中含有元素过多,那你应该考虑用类。而不是还在迷恋Java中介乎于普通变量与Class类之间的Collections类。
    比如如下方法就展示了试图把HashMap改成三元组的错误操作:

    public static void Maptest(){
    System.out.println("======Map错误的使用开始======");
    HashMap<String,String> map=new HashMap<String, String>();
    HashMap<String,HashMap<String, String>> bigmap=new HashMap<String, HashMap<String, String>>();
    map.put("key1","1");
    map.put("key2","2"); 
    bigmap.put("test1",map);
    map.clear();
    map.put("key1","3");
    map.put("key2","4"); 
    bigmap.put("test2",map);
    System.out.println(bigmap);
    System.out.println(bigmap.get("test1").get("key1"));
    System.out.println(bigmap.get("test1").get("key2"));
    System.out.println(bigmap.get("test2").get("key1"));
    System.out.println(bigmap.get("test2").get("key2"));
    System.out.println("======Map错误的使用结束======");
    System.out.println("======Map正确的使用开始======");
    map.clear();
    bigmap=null;
    map.put("key1","1");
    map.put("key2","2");
    map.put("key3","3");
    System.out.println(map);
    System.out.println("======Map正确的使用结束======");
    }
    

    在主函数调用这段代码,得到下面的运行结果:
    ======Map数据结构的测试开始======
    ======Map错误的使用开始======
    {test1={key2=4, key1=3}, test2={key2=4, key1=3}}
    3
    4
    3
    4
    ======Map错误的使用结束======
    ======Map正确的使用开始======
    {key3=3, key2=2, key1=1}
    ======Map正确的使用结束======
    ======Map数据结构的测试结束======
    这段程序本来用意是很明显,试图构造出一个{test1,key1,1},{test1,key2,2},{test2,key3,3},{test2,key4,4}
    然而,每个bigmap中还是存得都是那个map,你一旦把map清空,原来test1中的那个map也同样被清空, 有人试图创造多个map1,map2,...那你还不如用一个简单的类,看起来更加明确,而且类中以后还能写方法,被继承

    相关文章

      网友评论

          本文标题:Collection和Collections的区别

          本文链接:https://www.haomeiwen.com/subject/qsbozttx.html