Java SE学习总结 Day (20)


Day 20开篇:
      
        "
今天java基础主要学习了Map集合的概念,Map集合的子类,Map结构的理解,HashMap的底层原理,Map的常用法,获取的方法,泛型的概念,格式,好处等。 "




知识点反馈:

今天的知识点总结的思维导图

 

 
一.Map集合
1. 概念:
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值;将账号映射到账号的对象;一个映射不能包含重复的账号;每个账号最多只能映射到一个账号对象
(Map:双列集合,存储的是一个key-value对的数据)
 
举例说明:
我们的程序当中,需要存储好几百万个账号,账号具备密码、注册日期、登陆ip、账户余额等相关属性和行为假如说,我需要修改一个账号、查找一个账号。请问如何处理?
(1)存储到数组:
            A.先遍历,每遍历一次就取出对象具体的字段数据,一一比较!假如账号数据在最后一个元素(遍历几百万次)
(2)存储到集合:
            B..集合遍历的步骤基本是不是和数组一样??
所以数组操作的效率和集合基本等价像这种情况,我们就应该根据一个搜索条件,来获取该数据的所有所有结果,比如,你们学校可以根据你的学号获取到你们的所有信息,网站,根据账号也可以获取到所有信息。
 
而这种结构,其实就是一个所谓的双列结构<K,V>,java中的双列结构就是Map集合
Account(对象)
                |- 用户名
                |- 密码
                |- 余额
                ....
            Account ac = new Account();
 
            <"admin",ac>
            <"toobug",ac1>
            <"root",ac2>
2. Map集合的子类:
(1)HashMap:是我们Map集合的主要实现类,线程不同步,效率比较高,允许存储null值
(2)LinkedHashMap:在原有的HashMap上面,多新增了一个双向链表,保证在遍历的时候取出和存入的顺序是一致的
(3)TreeMap:可以对我们的Map集合的key进行排序,甚至可以使用自然排序或者定制排序
(4)Hashtable:一个非常古老的存在,线程安全,效率极低,不能存储null
(5)Properties:一般仅仅用于进行文件的配置,key和value都只能是String类型
3. Map结构的理解:
(1)Map的key:无序的、不可重复的,使用的Set来存储key
(2)Map的value:虽然说value采用的Collection进行存储,可以是有序的,但是value的数据结构应该跟着Key,所以仍然是无序的, 一个键只能对应一个值
(3)Map的Entry:无序的,不可重复的,因为Entry是跟着key来走
4. HashMap的底层原理:(JDK8的JDK7的区别)
(1)JDK7:new HashMap():底层会创建一个长度为16的数组进行维护
     JDK8:new HashMap():底层不会给数组指定长度,在第一次添加键值的时候进行扩容
(2)JDK7:数组的名字叫做Entry[]
     JDK8:数组的名字叫做Node[],而不是Entry[],但是本质上还是使用Map.Entry这个接口
(3)JDK7:底层全部采用数组+链表进行维护(具体回忆HashSet)
     JDK8:底层采用数组+链表,部分使用红黑树进行维护
(4)为什么多了一个红黑树?
     红黑树并不是会随时启用,当一个索引位置上的链表元素的数据个数>8且数组的长度>64的时候,索引上面的数据改用红黑树存储。为什么要红黑树,主要还是提高查找的效率。(类似于二分查找)
5. Map的常用方法:
(1)添加的方法:
               V put(K key, V value):给Map新增一个键值对,返回上一次添加的值,如果上一次不存在,则返回null
               voidputAll(Map<? extends K,? extends V> m):添加这个map集合
(2)删除的方法:
             V remove(Object key):根据键移除整个整个键值对元素
             void clear():移除所有键值对元素
(3)判断的方法:
             boolean containsKey(Object key):判断集合当中是否存在指定的键
             boolean containsValue(Object value):判断集合当中是否存在指定的值
             boolean isEmpty():判断集合是否为空
6. 获取的方法:
(1)V get(Object key):根据指定的键来获取值(注意:没有根据值来获取键这个说法,键是唯一的,而值是可重复
(2)Set<K> keySet():获取集合当中的所有键,使用Set来接收
(3)Collection<V> values:获取集合当中的所有的值,使用Collection接收
举例:
public class Demo02 {
    public static void main(String[] args) {
        //我想限定键值只能传入String类型的参数
        Map<String,String> map = new HashMap<String,String>();
        //添加元素
        map.put("刘恺威","杨幂");
        map.put("陈羽凡","白百何");
        map.put("谢霆锋","张柏芝");
        map.put("王宝强","马蓉");
        map.put("文章","马伊?");
 
        System.out.println("get:"+map.get("王宝强"));//键不存在返回null
        System.out.println("-------------------");
        //获取所有的键
        Set<String> set = map.keySet();
        for (String key : set){
            System.out.println(key);
        }
        System.out.println("-------------------");
        //获取所有的值
        Collection<String> values = map.values();
        for (String v : values){
            System.out.println(v);
        }
        System.out.println("-------------------");
        //我能不能将值和键全部获取出来
        Set<String> set1 = map.keySet();
        for (String s : set1){
            //通过键获取值
            String v = map.get(s);
            System.out.println("键:"+s+"---- 值:"+v);
        }
 
    }
}
7. Set<Map.Entry<K,V>>        entrySet():返回的是集合的键值对的集合
 
二.泛型
1. 概念:
其实也就是将运行时候才能确定类型的这个工作,提前到编译期就进行处理。这种集合的处理机制是jdk5的版本提供的【泛型】
2. 格式:
<数据类型> : 这里的数据只能是引用数据类型
 
举例:List<String> list = new ArrayList<String>()
3. 好处:
(1)避免了数据类型转换失败的问题
(2)可以在编译器当中,解决黄色警告线的问题
(3)可以避免强制类型转换
4.面试题:
请问泛型好处的是什么?在没有提供泛型之前JAVA是怎么处理的?
答:JDK1.5之前的所有版本把元素类型设计为了一个Object的数组,因为集合只能存储引用数据类型而Object恰哈是所有引用类型的基类,所以可以实现完全兼容,但是每一次使用集合,我们都需要考虑集合里面的数据是不是兼容,甚至还要考虑类型转换失败的异常。因此1.5版本之后,就允许选择性将元素设计一个特殊参数类型,这个类型被称之为泛型 List<E> Collection<E>,这个E 其实就是一个数据类型,可以是任意引用数据列席。
5.泛型的类定义:
请将obj这个参数变换成灵活参数(不在乎数据类型,任意数据类型都可以接受)
(1)方式一:
            使用Object作为参数代替,但是需要考虑类型的的问题
(2)方式二:
            使用泛型的类限定,
                定义:class ObjectTest<T>
                调用:ObjectTest<String> obj = new ObjectTest<String>();
 
这个类型限定的T,他不是一个明确的数据类型,原则上你写任何字母都是可以的。只不过一般都使用T、K、V、E来进行代替。这个T,其实就是Type的意思。T只能是一个类。不能使用任何的基本数据类型进行填充,但是可以是包装类。
 
6.注意:
(1)ObjectTest<T> ,T可以是一个明确的数据类型,如果你的类型已经明确好 可以直接写死。
(2)当一个泛型参数不够使用的时候,可以定义多个,格式:ObjectTest<T>
7.泛型通配:
当某一时刻,我们将一个集合是给所有所有人使用,但是这个集合没有立马实例化谁需要使用这个集合,谁自己进行实例,那么这个时刻我们就没办法明确泛型的数据类型,
可以使用 ? 进行泛型任意通配
(1)任意类型,如果没有进行明确,那么就是Object所有子类都允许
                Collection<Object> c;
                c = new ArrayList<Object>();
(2)我们有的时候无法明确,但是要求其传入的数据类型必须是某某的子类的时候
                extends 父类型
                Collection<? extends  Animal> c3 = new ArrayList<Cat>();
(3)我们有的时候无法明确,但是要求其传入的数据类型必须是某某的父类的时候
                super 本类
                Collection<? super Animal> c2 = new ArrayList<Object>();
8. 例子:
一个班级里面有很多学生, 一个年级(学校)又有很多班级,请使用集合对上述的场景进行描述,使用最安全,最可靠的方式写出代码
public class Demo07 {
    public static void main(String[] args) {
        //创建一个集合来存储学生
 
        //一个班级
        List<Student> list = new ArrayList<Student>();
        //学生进班
        list.add(new Student("张三", 12));
        list.add(new Student("李四", 15));
        list.add(new Student("王五", 11));
        list.add(new Student("赵六", 19));
        list.add(new Student("田七", 20));
 
        //二个班级
        List<Student> list2 = new ArrayList<Student>();
        //学生进班
        list2.add(new Student("张三", 12));
        list2.add(new Student("李四", 15));
        list2.add(new Student("王五", 11));
        list2.add(new Student("赵六", 19));
        list2.add(new Student("田七", 20));
 
        //三个班级
        List<Student> list3 = new ArrayList<Student>();
        //学生进班
        list3.add(new Student("张三", 12));
        list3.add(new Student("李四", 15));
        list3.add(new Student("王五", 11));
        list3.add(new Student("赵六", 19));
        list3.add(new Student("田七", 20));
        
        
        //班级进入到学校
        //学校里面存储是班级,谁代表班级?List???  --> List<Student>
        List l1 = new ArrayList();
        List<List<Student>> s = new ArrayList <List<Student>>();
        l1.add("阿斯达所大所");
        s.add(list);
        s.add(list2);
        s.add(list3);
        //不合理
        s.add(l1);
 
        //遍历
        //遍历的顺序 从学校,取出所有班级
        //从班级取出所有学生
        for(List<Student> l : s){
            for (Student stu : l){
                System.out.println("姓名:"+stu.name+"  年龄:"+stu.age);
            }
            System.out.println("-------------------------");
        }
 
    }
 
}
 
发布了29 篇原创文章 · 获赞 7 · 访问量 3162

猜你喜欢

转载自blog.csdn.net/weixin_45406656/article/details/104271567