JAVA基础之集合框架详解

2018-09-18  本文已影响6人  Owen270

参考文章:
https://www.cnblogs.com/xiaoxi/p/6089984.html
http://www.importnew.com/16658.html

1.集合框架图

Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类。

image.png

2.Collection接口(Collection包含了List和Set两大分支。)

2.1 List接口的实现类(ArrayList,Vector,LinkedList,Stack)

(1).ArrayList

ArrayList是一个动态数组,它允许任何符合规则的元素插入甚至包括null,每一个ArrayList都有一个初始容量(10),随着容器中的元素不断增加,容器的大小也会随着增加。在每次向容器中增加元素的同时都会进行容量检查,当快溢出时,就会进行扩容操作。所以如果我们明确所插入元素的多少,最好指定一个初始容量值,避免过多的进行扩容操作而浪费时间、效率。

注意: ArrayList擅长于随机访问。同时ArrayList是非同步的。
(2).Vector

与ArrayList相似,但是Vector是同步的。所以说Vector是线程安全的动态数组。它的操作与ArrayList几乎一样。

(3).LinkedList

同样实现List接口的LinkedList与ArrayList不同,ArrayList是一个动态数组,而LinkedList是一个双向链表,
由于实现的方式不同,LinkedList不能随机访问,它所有的操作都是要按照双重链表的需要执行。在列表中索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。这样做的好处就是可以通过较低的代价在List中进行插入和删除操作。
与ArrayList一样,LinkedList也是非同步的。如果多个线程同时访问一个List,则必须自己实现访问同步。

注意:创建List时构造一个同步的List:List list = Collections.synchronizedList(new LinkedList(...));
(4).Stack

Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop 方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。

   private static void testStack() {
        /***
         * 栈是一种只能在一端进行插入或删除操作的线性表
         * 特性:先进后出
         */
        Stack<String> stack=new Stack<>();
        //进栈push()
        stack.push("1");
        stack.push("2");
        stack.push("3");
        stack.push("4");
        System.out.println("statck data:"+stack.toString());
        // 取栈顶值(不出栈)
        System.out.println("stack top:"+stack.peek());
        //出栈
        //  stack.pop();
        // stack.pop();
        //stack.pop();
        System.out.println("stack data:"+stack.toString());
        System.out.println("stack is empty:"+stack.empty());
        int index=stack.search("3");//计数从顶部开始
        System.out.println("stack search index:"+index);
        System.out.println("stack search result:"+ stack.get(0));

        List<String> list=new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        System.out.println("list is empty:"+list.get(3));
        Iterator<String> iterator=list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

2.2 Set接口的实现类(HashSet,LinkedHashSet,TreeSet)

(1)HashSet

HashSet 是一个没有重复元素的集合。它是由HashMap实现的,不保证元素的顺序(这里所说的没有顺序是指:元素插入的顺序与输出的顺序不一致),而且HashSet允许使用null 元素。HashSet是非同步的,如果多个线程同时访问一个哈希set,而其中至少一个线程修改了该set,那么它必须保持外部同步。 HashSet按Hash算法来存储集合的元素,因此具有很好的存取和查找性能。

注意:HashSet是由HashMap实现,不保证元素的插入顺序,可以存放null值,仅仅能够存入一个null值。
 private static void testHashSet() {
        /****
         * 元素不重复
         */
        Set<String> hashSet=new HashSet<>();
        hashSet.add("javabbb");
        hashSet.add("java01");
        hashSet.add("java01");
        hashSet.add("java03");
        hashSet.add("java02");
        Set<String>  hashSet1=new HashSet<>();
        hashSet1.add("java05");
        hashSet1.add("java04");
        hashSet1.add("javaaaa");
        hashSet.add(null);//可以插入null
        hashSet.add(null);
        hashSet.addAll(hashSet1);
        boolean isEmpty=hashSet.isEmpty();
        //遍历
        Iterator<String> iterator= hashSet.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

输出结果:


image.png
(2)LinkedHashSet

LinkedHashSet继承自HashSet,其底层是基于LinkedHashMap来实现的,有序,非同步。LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。

注意:LinkedHashSet底层是基于LinkedHashMap来实现
 private static void testLinkedHashSet() {
        /****
         * 因为是链表,所以有序输出
         * 元素不重复
         */
        Set<String> linkedHashSet=new LinkedHashSet<>();
        linkedHashSet.add("java01");
        linkedHashSet.add("java01");
        linkedHashSet.add("java02");
        linkedHashSet.add("java03");
        Set<String> linkedHashSet1=new LinkedHashSet<>();
        linkedHashSet1.add("java04");
        linkedHashSet1.add("java05");
        linkedHashSet1.add(null);
        linkedHashSet1.add(null);
        linkedHashSet.addAll(linkedHashSet1);
        //遍历
        Iterator<String> iterator= linkedHashSet.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

    }

输出结果:


image.png
(3)TreeSet

TreeSet是一个有序集合,其底层是基于TreeMap实现的,非线程安全。TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序和定制排序,其中自然排序为默认的排序方式。当我们构造TreeSet时,若使用不带参数的构造函数,则TreeSet的使用自然比较器;若用户需要使用自定义的比较器,则需要使用带比较器的参数。

注意:TreeSet底层是基于TreeMap来实现,Set集合都是非线程安全的

    private static void testIntegerSort() {
        System.out.println("Integer对象自然排序:");
        TreeSet<Integer> treeSetFirst = new TreeSet<>();
        treeSetFirst.add(2);
        treeSetFirst.add(1);
        treeSetFirst.add(4);
        treeSetFirst.add(3);
        treeSetFirst.add(5);
        Iterator<Integer> iterator=treeSetFirst.iterator();
        while (iterator.hasNext()){
                System.out.println(iterator.next());
        }
    }
    private static void testDictionarySort() {
        System.out.println("Dictionary对象自然排序:");
        TreeSet<String> treeSetFirst = new TreeSet<>();
        treeSetFirst.add("Baidu");
        treeSetFirst.add("Tecent");
        treeSetFirst.add("Ali");
        treeSetFirst.add("WanDa");
        treeSetFirst.add("HengDa");
        treeSetFirst.add("12");
        treeSetFirst.add("23a#");
        treeSetFirst.add("#");
        Iterator<String> iterator=treeSetFirst.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }


    private static void testCompatorSort() {
        Set<Student> treeSet=new TreeSet<>();
        treeSet.add(new Student("tecent",2));
        treeSet.add(new Student("JD",1));
        treeSet.add(new Student("wanda",3));
        treeSet.add(new Student("baidu",2));
        treeSet.add(new Student("ali",2));
        treeSet.add(new Student("tecent",2));//重复的元素被剔除了
        System.out.println(treeSet);
        Iterator itTSet = treeSet.iterator();//遍历输出
        while(itTSet.hasNext()){
            System.out.print(itTSet.next() + "\n");
        }
    }

    private static void testSubHeadTailSet() {
        TreeSet nums = new TreeSet();
        nums.add(5);
        nums.add(2);
        nums.add(3);
        nums.add(8);
        nums.add(8);
        //输出集合元素,可以看到集合元素已经处于排序状态,输出【2,3,5,8】
        System.out.println(nums);
        //输出排序后集合里的第一个元素2
        System.out.println(nums.first());
        //输出排序后集合里最后一个元素
        System.out.println(nums.last());
        //输出小于4的集合,不包含4,输出【2,3】
        System.out.println(nums.headSet(4));
        //输出大于5的集合,如果set集合中有5,子集中还应该有5,输出【5,8】
        System.out.println(nums.tailSet(5));
        //输出大于2,小于5的子集,包括2,不包括5,输出集合【2,3】
        System.out.println(nums.subSet(2, 5));
    }
    public static class Student implements Comparable {
        int num;
        String name;

        public Student( String name,int num) {
            this.num = num;
            this.name = name;
        }

        @Override
        public String toString() {
            return "StudentNo:" + num + " ,StudentName:" + name      ;
        }

        public int getNum() {
            return num;
        }

        public void setNum(int num) {
            this.num = num;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        public int compareTo(Object o) {
            Student student= (Student) o;
            if(num<student.getNum()){//升序排列
                return -1;
            }else if(num==student.getNum()){
                return name.compareTo(student.getName());
            }else{
                return 1;
            }

        }
    }

输出结果:


image.png

3.Map接口

Map与List、Set接口不同,它是由一系列键值对组成的集合,提供了key到Value的映射。同时它也没有继承Collection。在Map中它保证了key与value之间的一一对应关系。也就是说一个key对应一个value,所以它不能存在相同的key值,当然value值可以相同。

(1).HashMap

HashMap可以通过调用Collections的静态方法Collections.synchronizedMap(Map map)进行同步,最多只允许一条记录的键为Null,不支持线程的同步,无序

    private static void testHashMap() {
        /***
         * hashmap的key和value都可以为null
         */
        Map<String, String> map = new HashMap<>();
        for (int i = 0; i <= 3; i++) {
            map.put("key" + i, "value" + i);
        }
        map.put(null,"value4");
        map.put(null,"value5");
        map.put("key6",null);
        map.put("key7",null);
        map.get("key" + 5);
        for (String key : map.keySet()) {
            System.out.println(map.get(key));
        }
    }

输出结果:


image.png

输出结果:


image.png

(2).LinkedHashMap

LinkedHashMap是HashMap的一个子类,它保留插入的顺序,如果需要输出的顺序和输入时的相同,那么就选用LinkedHashMap。允许使用null值和null键

private static void testLinkHashMap() {
        //linkedhashmap  extends hashmap 比hashmap功能更强大
        Map<String, String> map = new LinkedHashMap<>();
        for (int i = 0; i <= 3; i++) {
            map.put("key" + i, "value" + i);
        }
        map.put(null,"value4");
        map.put(null,"value5");
        map.put("key6",null);
        map.put("key7",null);
        map.get("key" + 5);
        for (String key : map.keySet()) {
            System.out.println(map.get(key));
        }
    }

输出结果:


image.png

(2).Hashtable

线程同步,同时key,value都不可以为null,无序的

private static void testHashtable() {
        /***
         * 线程同步的,同时key,value都不可以为null,无序的
         */
        Hashtable<String,Object> hashtable = new Hashtable();
        hashtable.put("baidu","101");
        hashtable.put("ali","102");
        hashtable.put("tencent","103");
        hashtable.put("wanda","105");
        hashtable.put("pingan","107");
        hashtable.put("hengda","106");
        hashtable.put("transsion","104");
        // hashtable.put(null,"2");//java.lang.NullPointerException
        //  hashtable.put("wanke",null);//java.lang.NullPointerException
        for(String key:hashtable.keySet()){
            System.out.println(key+"="+hashtable.get(key));
        }
    }

(4).ConCurrentHashMap

ConcurrentHashMap和HashTable都是线程安全的,无序的,key和value都不能为null,性能上要比Hashtable要强,是一个加强版本的Hashtable。

private static void testConcurrentHashMap() {
        /***
         * ConcurrentHashMap和HashTable都是线程安全的,可以在多线程中进行,
         * key和value都不能为null,性能上要比Hashtable要强
         * 线程同步的,同时key,value都不可以为null
         */
        ConcurrentHashMap<String,Object> concurrentHashMap = new ConcurrentHashMap();
        concurrentHashMap.put("baidu","101");
        concurrentHashMap.put("ali","102");
        concurrentHashMap.put("tencent","103");
        concurrentHashMap.put("wanda","105");
        concurrentHashMap.put("pingan","107");
        concurrentHashMap.put("hengda","106");
        concurrentHashMap.put("transsion","104");
        // concurrentHashMap.put(null,"2");//java.lang.NullPointerException
        // concurrentHashMap.put("wanke",null);//java.lang.NullPointerException
        for(String key:concurrentHashMap.keySet()){
            System.out.println(key+"="+concurrentHashMap.get(key));
        }
    }

输出结果:


image.png

(5).TreeMap

TreeMap 是一个有序的key-value集合,非同步,基于红黑树(Red-Black tree)实现,每一个key-value节点作为红黑树的一个节点。TreeMap存储时会进行排序的,会根据key来对key-value键值对进行排序,其中排序方式也是分为两种,一种是自然排序,一种是定制排序,具体取决于使用的构造方法。

注意:key不能为null,value可以为null
 //自然排序顺序:
    public static void naturalSort(){
        //第一种情况:Integer对象
        System.out.println("Integer对象自然排序:");
        TreeMap<Integer,String> treeMapFirst = new TreeMap<Integer, String>();
        treeMapFirst.put(1,"jiaboyan");
        treeMapFirst.put(6,"jiaboyan");
        treeMapFirst.put(3,"jiaboyan");
        treeMapFirst.put(10,"jiaboyan");
        treeMapFirst.put(7,"jiaboyan");
        treeMapFirst.put(13,"jiaboyan");
        //treeMapFirst.put(null,"jiaboyan");java.lang.NullPointerException
        treeMapFirst.put(14,null);//可以运行
        System.out.println(treeMapFirst.toString());

        //第二种情况:SortedTest对象
        System.out.println("SortedTest对象排序一:");
        TreeMap<SortedTest,String> treeMapSecond = new TreeMap<SortedTest, String>();
        treeMapSecond.put(new SortedTest(10),"jiaboyan");
        treeMapSecond.put(new SortedTest(1),"jiaboyan");
        treeMapSecond.put(new SortedTest(13),"jiaboyan");
        treeMapSecond.put(new SortedTest(4),"jiaboyan");
        treeMapSecond.put(new SortedTest(0),"jiaboyan");
        treeMapSecond.put(new SortedTest(9),"jiaboyan");
        System.out.println(treeMapSecond.toString());
        //默认是根据key的自然排序来组织(比如integer的大小,String的字典排序)
        System.out.println("integer和字典对象排序二:");
        TreeMap<String,SortedTest> treeMapThree = new TreeMap<String,SortedTest >();
        treeMapThree.put("2key1",new SortedTest(10));
        treeMapThree.put("1key2",new SortedTest(1));
        treeMapThree.put("bey3",new SortedTest(13));
        treeMapThree.put("key6",new SortedTest(4));
        treeMapThree.put("key5",new SortedTest(0));
        treeMapThree.put("key4",new SortedTest(9));
        System.out.println(treeMapThree.toString());
    }

    public static class SortedTest implements Comparable<SortedTest> {
        private int age;
        public SortedTest(int age){
            this.age = age;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return "age:"+age;
        }

        //自定义对象,实现compareTo(T o)方法:
        public int compareTo(SortedTest sortedTest) {
            int num = this.age - sortedTest.getAge();
            //为0时候,两者相同:
            if(num==0){
                return 0;
                //大于0时,传入的参数小:
            }else if(num>0){
                return 1;
                //小于0时,传入的参数大:
            }else{
                return -1;
            }
        }
    }

输出结果:


image.png
上一篇下一篇

猜你喜欢

热点阅读