集合框架知识点(全)

1.集合概述

     A:集合的由来

        * 数组长度是固定,当添加的元素超过了数组的长度时需要对数组重新定义,太麻烦,java内部给我们提供了集合类,能存储任意对  象,长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少

    * B:数组和集合的区别
        * 区别1 :
            * 数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值
            * 集合只能存储引用数据类型(对象)集合中也可以存储基本数据类型,但是在存储的时候会自动装箱变成对象
        * 区别2:
            * 数组长度是固定的,不能自动增长
            * 集合的长度的是可变的,可以根据元素的增加而增长
    * C:数组和集合什么时候用
        * 1,如果元素个数是固定的推荐用数组
        * 2,如果元素个数不是固定的推荐用集合

    * D:集合继承体系图(待修改)

集合框架知识点(全)_第1张图片

   Iterator:迭代器,用于集合的迭代(遍历)

       1. Collection:单列集合的根接口
            a:List:集合有序    -->   ListIterator
                1).ArrayList:底层数组实现,特点:查询快,因为有索引
                2).LinkedList:底层链表实现,特点:增删快,可以在链表中直接连接插入或增添数据
                3).Vector:线程安全
            b:Set:无序,不重复
                1).TreeSet:自然排序
                2).HashSet
                        i:LinkedHashSet:可以保证怎么存就怎么取
           
        2.Map:双列集合的根接口
            a:TreeMap:二叉树实现
            b:HashMap:Hash算法
                1). LinkedHashMap:底层是链表实现的可以保证怎么存就怎么取
            c:HashTable不可以存储null键和null值




2.集合的遍历
    集合的遍历
        * 其实就是依次获取集合中的每一个元素。
    1.集合转数组遍历
        * 把集合转成数组,可以实现集合的遍历
        * toArray()
        *
            Collection coll = new ArrayList();
            coll.add(new Student("张三",23));        //Object obj = new Student("张三",23);
            coll.add(new Student("李四",24));
            coll.add(new Student("王五",25));
            coll.add(new Student("赵六",26));
            
            Object[] arr = coll.toArray();                //将集合转换成数组
            for (int i = 0; i < arr.length; i++) {
                Student s = (Student)arr[i];            //强转成Student
                System.out.println(s.getName() + "," + s.getAge());
            }

    2.迭代器遍历
        * A:迭代器概述
            * 集合是用来存储元素,存储的元素需要查看,那么就需要迭代(遍历)
        * B:案例演示
            * 迭代器的使用
        
            Collection c = new ArrayList();
            c.add("a");
            c.add("b");
            c.add("c");
            c.add("d");
            
            Iterator it = c.iterator();                        //获取迭代器的引用
            while(it.hasNext()) {                            //集合中的迭代方法(遍历)
                System.out.println(it.next());
            }

    3.Vector的迭代
            Vector v = new Vector();                //创建集合对象,List的子类
            v.addElement("a");
            v.addElement("b");
            v.addElement("c");
            v.addElement("d");
            
            //Vector迭代
            Enumeration en = v.elements();            //获取枚举
            while(en.hasMoreElements()) {            //判断集合中是否有元素
                System.out.println(en.nextElement());//获取集合中的元素
            }

3.并发修改异常

        原因: 迭代器遍历,集合修改集合(ConcurrentModificationException并发修改异常)

        需求:我有一个集合,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"java"元素,请写代码实现。

         这个会发生并发修改异常:

            List list = new ArrayList();
            list.add("a");
            list.add("b");
            list.add("world");
            list.add("d");
            list.add("e");
            
            Iterator it = list.iterator();
            while(it.hasNext()) {
                String str = (String)it.next();
                if(str.equals("world")) {
                    list.add("java");            //这里会抛出ConcurrentModificationException并发修改异常
                }
            }


            
        解决方案
            * 方案一:迭代器迭代元素,迭代器修改元素(ListIterator的特有功能add)
            * 方案二:集合遍历元素,集合修改元素
            ListIterator lit = list.listIterator();        //如果想在遍历的过程中添加元素,可以用ListIterator中的add方法
            while(lit.hasNext()) {
                String str = (String)lit.next();
                if(str.equals("world")) {
                    lit.add("javaee");    
                    //list.add("javaee");
                }
            }

4.数据结构之数组和链表
    * A:数组
        * 查询快修改也快
        * 增删慢
    * B:链表
        * 查询慢,修改也慢
        * 增删快


5.List的三个子类的特点以及异同

        ArrayList:
            底层数据结构是数组,查询快,增删慢。
            线程不安全,效率高。
         Vector:
            底层数据结构是数组,查询快,增删慢。
            线程安全,效率低。
            Vector相对ArrayList查询慢(线程安全的)
            Vector相对LinkedList增删慢(数组结构)
         LinkedList:
            底层数据结构是链表,查询慢,增删快。
            线程不安全,效率高。

         Vector和ArrayList的区别
            Vector是线程安全的,效率低
            ArrayList是线程不安全的,效率高
         Vector和ArrayList的共同点:都是数组实现的

        ArrayList和LinkedList的区别
            ArrayList底层是数组结果,查询和修改快
            LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢
        ArrayList和LinkedList的共同点:都是线程不安全的

    List有三个儿子,我们到底使用谁呢?
        查询多用ArrayList
        增删多用LinkedList
        如果都多ArrayList

6.ArrayList去除重复元素
    方法一:新建空集合,遍历再比较(如果元素是自定义对象,则要重写equals()方法)
        public static ArrayList getSingle(ArrayList list) {
                ArrayList newList = new ArrayList();            //创建一个新集合
                Iterator it = list.iterator();                //获取迭代器
                while(it.hasNext()) {                    //判断老集合中是否有元素
                    String temp = (String)it.next();        //将每一个元素临时记录住
                    if(!newList.contains(temp)) {            //如果新集合中不包含该元素
                        newList.add(temp);            //将该元素添加到新集合中
                    }
                }
                return newList;                        //将新集合返回
            }



    方法二:利用Set集合元素唯一性,    而LinkedHashSet可以保证存取的顺序不变    
                ArrayList list = new ArrayList<>();
                list.add("a");
                list.add("a");
                list.add("a");
                list.add("b");
                list.add("b");
                LinkedHashSet lhs = new LinkedHashSet<>();    //创建一个Set集合
                lhs.addAll(list);                    //将list集合中的所有元素添加到lhs
                list.clear();                        //清空原集合
                list.addAll(lhs);

7.LinkedList类特有功能
    * public void addFirst(E e)及addLast(E e)
    * public E getFirst()及getLast()
    * public E removeFirst()及public E removeLast()
    * public E get(int index);

8.泛型
    泛型的由来:通过Object转型问题引入
    * 早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。也就存在这隐患,所以Java提供了泛型来解决这个安全问题。

    * A:泛型类概述
        * 把泛型定义在类上
        定义格式
        * public class 类名<泛型类型1,…>
        注意事项    
        * 泛型类型必须是引用类型

    * B:泛型方法概述
        * 把泛型定义在方法上
        定义格式    
        * public <泛型类型> 返回类型 方法名(泛型类型 变量名)


    * C:泛型接口概述
        * 把泛型定义在接口上
        定义格式    
        * public interface 接口名<泛型类型>

    * D:泛型高级之通配符(了解)
        * A:泛型通配符
            * 任意类型,如果没有明确,那么就是Object以及任意的Java类了
        * B:? extends E
            * 向下限定,E及其子类
        * C:? super E
            * 向上限定,E及其父类


9.增强for概述
    * 简化数组和Collection集合的遍历
    格式:
        for(元素数据类型 变量 : 数组或者Collection集合) {
            使用变量即可,该变量就是元素
        }

     ArrayList存储字符串并遍历增强for版
            ArrayList list = new ArrayList<>();
            list.add("a");
            list.add("b");
            list.add("c");
            list.add("d");
            
            for(String s : list) {
                System.out.println(s);
            }

10.三种迭代的能否删除
    * 普通for循环,可以删除,但是索引要--
    * 迭代器,可以删除,但是必须使用迭代器自身的remove方法,否则会出现并发修改异常
    * 增强for循环不能删除

11.静态导入
    格式:
        * import static 包名….类名.方法名;
        * 可以直接导入到方法的级别
    注意事项
        * 方法必须是静态的,如果有多个同名的静态方法,容易不知道使用谁?这个时候要使用,必须加前缀。由此可见,意义不大,所以一般不用,但是要能看懂。
可变参数概述
        * 定义方法的时候不知道该定义多少个参数
    格式
        * 修饰符 返回值类型 方法名(数据类型…  变量名){}
    注意事项:
        * 这里的变量其实是一个数组
        * 如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个

     集合嵌套之ArrayList嵌套ArrayList

12.HashSet存储自定义对象保证元素唯一性
            HashSet hs = new HashSet<>();
            hs.add(new Person("张三", 23));
            hs.add(new Person("张三", 23));
            hs.add(new Person("李四", 23));
            hs.add(new Person("李四", 23));
            hs.add(new Person("王五", 23));
            hs.add(new Person("赵六", 23));
            // 重写Person的hashCode()和equals()方法
           

13.HashSet原理
    * 我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数
    * 当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象
        * 如果没有哈希值相同的对象就直接存入集合
        * 如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存

14.将自定义类的对象存入HashSet去重复
    * 类中必须重写hashCode()和equals()方法
    * hashCode(): 属性相同的对象返回值必须相同, 属性不同的返回值尽量不同(提高效率)
    * equals(): 属性相同返回true, 属性不同返回false,返回false的时候存储

15.TreeSet保证元素唯一和自然排序
    1.特点
    * TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列
    2.使用方式
    * a.自然顺序(Comparable)
        * TreeSet类的add()方法中会把存入的对象提升为Comparable类型
        * 调用对象的compareTo()方法和集合中的对象比较
        * 根据compareTo()方法返回的结果进行存储
    * b.比较器顺序(Comparator)
        * 创建TreeSet的时候可以制定 一个Comparator
        * 如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序
        * add()方法内部会自动调用Comparator接口中compare()方法排序
        * 调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数
    * c.两种方式的区别
        * TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)
        * TreeSet如果传入Comparator, 就优先按照Comparator


16.Map接口概述
    * 查看API可以知道:
        * 将键映射到值的对象
        * 一个映射不能包含重复的键
        * 每个键最多只能映射到一个值

17.Map接口和Collection接口的不同
    * Map是双列的,Collection是单列的
    * Map的键唯一,Collection的子体系Set是唯一的
    * Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效

18.Map集合的获取功能
        * Set> entrySet():获取所有的键值对象的集合
        * V get(Object key):根据键获取值
        * Set keySet():获取集合中所有键的集合
        * Collection values():获取集合中所有值的集合

19.利用HashMap统计字符串中每个字符出现的次数
            String str = "aaaabbbcccccccccc";
            char[] arr = str.toCharArray();                        //将字符串转换成字符数组
            HashMap hm = new HashMap<>();    //创建双列集合存储键和值
            
            for(char c : arr) {                                    //遍历字符数组
                /*if(!hm.containsKey(c)) {                        //如果不包含这个键
                    hm.put(c, 1);                                //就将键和值为1添加
                }else {                                            //如果包含这个键
                    hm.put(c, hm.get(c) + 1);                    //就将键和值再加1添加进来
                }
                
                //hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) + 1);
                Integer i = !hm.containsKey(c) ? hm.put(c, 1) : hm.put(c, hm.get(c) + 1);
                        }
            
            for (Character key : hm.keySet()) {                    //遍历双列集合
                System.out.println(key + "=" + hm.get(key));
            }




20.HashMap和Hashtable的区别
        * Hashtable是JDK1.0版本出现的,是线程安全的,效率低,HashMap是JDK1.2版本出现的,是线程不安全的,效率高

        * Hashtable不可以存储null键和null值,HashMap可以存储null键和null值




21.模拟斗地主洗牌和发牌并对牌进行排序的代码实现(HashMap,TreeMap,ArrayList,Collections的)
            //买一副牌
            String[] num = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
            String[] color = {"方片","梅花","红桃","黑桃"};
            HashMap hm = new HashMap<>();            //存储索引和扑克牌
            ArrayList list = new ArrayList<>();            //存储索引
            int index = 0;                            //索引的开始值
            for(String s1 : num) {
                for(String s2 : color) {
                    hm.put(index, s2.concat(s1));            //将索引和扑克牌添加到HashMap中
                    list.add(index);                //将索引添加到ArrayList集合中
                    index++;
                }
            }
            hm.put(index, "小王");
            list.add(index);
            index++;
            hm.put(index, "大王");
            list.add(index);
            //洗牌
            Collections.shuffle(list);
            //发牌
            TreeSet gaojin = new TreeSet<>();
            TreeSet longwu = new TreeSet<>();
            TreeSet me = new TreeSet<>();
            TreeSet dipai = new TreeSet<>();
            
            for(int i = 0; i < list.size(); i++) {
                if(i >= list.size() - 3) {
                    dipai.add(list.get(i));             //将list集合中的索引添加到TreeSet集合中会自动排序
                }else if(i % 3 == 0) {
                    gaojin.add(list.get(i));
                }else if(i % 3 == 1) {
                    longwu.add(list.get(i));
                }else {
                    me.add(list.get(i));
                }
            }
            
            //看牌
            lookPoker("高进", gaojin, hm);
            lookPoker("龙五", longwu, hm);
            lookPoker("冯佳", me, hm);
            lookPoker("底牌", dipai, hm);
            
        }
        
        public static void lookPoker(String name,TreeSet ts,HashMap hm) {
            System.out.print(name + "的牌是:");
            for (Integer index : ts) {
                System.out.print(hm.get(index) + " ");
            }
            
            System.out.println();
        }


你可能感兴趣的:(java基础)