黑马视频 (7/ 4)


Java SE


day15 集合框架

  • 引用数据类型数组中存储的都是 地址值 。
  • 数组长度是固定,当添加的元素超过了数组的长度时需要对数组重新定义,太麻烦,java内部给我们提供了集合类,能存储任意对象,长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少
  • 数组和集合的区别

    • 区别1 :

      • 数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值
      • 集合只能存储引用数据类型(对象),集合中也可以存储基本数据类型,但是在存储的时候会自动装箱变成对象,自动装箱在集合中引用的特别广泛
    • 区别2:

      • 数组长度是固定的,不能自动增长
      • 集合的长度的是可变的,可以根据元素的增加而增长
  • 数组和集合什么时候用

    • 如果元素个数是固定的推荐用数组,效率比较高
    • 如果元素个数不是固定的推荐用集合
  • 集合框架 ( Collection 集合的基本功能测试 )
  • 基本功能演示

    • boolean add(E e) ,可以添加任意对象,使用List添加会一直返回 true ,因为 list 中可以保存重复元素,使用 Set 添加重复元素会返回 false ,将一个集合当做一个元素添加进另一个集合
    • boolean remove(Object o) ,移除
    • void clear() ,清空
    • boolean contains(Object o) ,是否包含
    • boolean isEmpty(),是否为空
    • int size(),获取其中元素个数
    • collectionXxx.java 使用了未经检查或不安全的操作,注意:要了解详细信息请使用 -Xlint:unchecked重新编译,java编译器认为该程序存在安全隐患 。
  • toArray() 用于将集合转换为数组
  • 集合框架 Collection集合的带All功能
  • 带All的功能演示

    • boolean addAll(Collection c) ,将集合中的每一个元素添加进去另一个集合
    • boolean removeAll(Collection c), 删除交集,两个集合中都有的元素
    • boolean containsAll(Collection c),判断调用的集合是否包含传入的集合
    • boolean retainAll(Collection c),取交集,如果调用的集合改变就返回 true ,不变就返回 false
  • 集合是用来存储元素,存储的元素需要查看,那么就需要迭代(遍历)
  • 迭代器原理:迭代器是对集合进行遍历,而每一个集合内部的存储结构都是不同的,所以每一个集合存和取都是不一样,那么就需要在每一个类中定义 hasNext() 和 next() 方法,这样做是可以的,但是会让整个集合体系过于臃肿,迭代器是将这样的方法向上抽取出接。,然后在每个类的内部,定义自己迭代方式:这样做的好处有二,第一规定了整个集合体系的遍历方式都是hasNext() 和 next() 方法,第二,代码有底层内部实现,使用者不用管怎么实现的,会用即可
  • next() 方法用于将指针向后移动一位,
  • 迭代器源码解析

    • 1,在eclipse中ctrl + shift + t找到ArrayList类
    • 2,ctrl+o查找iterator()方法
    • 3,查看返回值类型是new Itr(),说明Itr这个类实现Iterator接口
    • 4,查找Itr这个内部类,发现重写了Iterator中的所有抽象方法
  • List 集合的特有功能概述

    • void add(int index,E element) , 可以在指定位置添加元素。 index 可以小于等于 size ,大于等于0,但是如果是其他的会报异常
    • E remove(int index) ,通过索引去删除元素,将删除的元素返回,删除的时候不会自动装箱,
    • E get(int index), 通过索引得到该元素,
    • E set(int index,E element),修改指定元素的值
  • ConcurrentModificationException出现 :迭代器迭代元素,迭代器修改元素 ( ListIterator 的特有功能 add ) ,这个迭代器是 list 集合特有的,可以在迭代的时候往集合内添加元素
  • ListIterator

    • boolean hasNext() , 是否有下一个
    • boolean hasPrevious() , 是否有前一个
    • Object next() , 返回下一个元素
    • Object previous(),返回上一个元素
  • :数组实现

    • 查询快修改也快
    • 增删慢
  • 链表实现

    • 查询慢,修改也慢
    • 增删快
  • List的三个子类的特点

    • ArrayList:

      • 底层数据结构是数组,查询快,增删慢。
      • 线程不安全,效率高。
    • Vector:

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

    • 底层数据结构是链表,查询慢,增删快。
    • 线程不安全,效率高。
  • Vector 和 ArrayList 的区别

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

    • ArrayList 底层是数组结果,查询和修改快
    • LinkedList 底层是链表结构的,增和删比较快,查询和修改比较慢
  • 共同点:都是线程不安全的
  • List有三个儿子

    • 查询多用 ArrayList
    • 增删多用 LinkedList
    • 如果都多 ArrayList

day16 List 集合

  • contains 方法,判断是否包含,底层依赖的是 equals 方法,
  • remove 方法,判断是否删除,底层依赖的也是 equals 方法。
  • LinkedList 类特有功能

    • public void addFirst(E e) 及 addLast(E e),在集合首部或者集合尾部添加
    • public E getFirst()及getLast(),获取第一个或者最后一个元素
    • public E removeFirst() 及 public E removeLast() ,删除头或者删除尾部,
    • public E get(int index) , 通过给的索引查找相应的值,查找慢,因为他的查找不是从头就是从尾开始。
  • 栈 (FILO)

    • 先进后出
  • 队列(FIFO )

    • 先进先出
  • next() 方法只能调用一次,调用多次将导致指针向后移动多次。
  • 泛型好处

    • 提高安全性 ( 将运行期的错误转换到编译期 )
    • 省去强转的麻烦
  • 泛型基本使用

    • < > 中放的必须是 引用数据类型 ,表示了这个集合能存储什么样的引用数据类型
  • 泛型使用注意事项

    • Object 泛型加不加无所谓。
    • 前后的泛型必须一致,或者后面的泛型可以省略不写(1.7的新特性菱形泛型)
  • 数组要保证前后的数据类型一致
  • 泛型的由来:通过 Object 转型问题引入

    • 早期的 Object 类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。也就存在着隐患,所以 Java 提供了泛型来解决这个安全问题。
  • 泛型类,在类上加泛型,public <泛型类型> 返回类型 方法名 ( 泛型类型 变量名 ) ,方法泛型最好和类泛型一致,如果不一致,需要在方法上声明该泛型。
  • 泛型接口概述 : 把泛型定义在接口上
  • 定义格式: public interface 接口名 < 泛型类型 > ,实现这个接口的方法的类型,和接口所定义的泛型一致。
  • 泛型通配符 < ? > ,可以替代任意一种类型,右边不确定泛型的时候,左边可以指定为 问号 。

    • 任意类型,如果没有明确,那么就是 Object 以及任意的 Java 类了
  • ? extends E : 向下限定,E 及其子类
  • ? super E : 向上限定,E 及其父类
  • foreach 循环 ,底层依赖的是迭代器,

      for ( 元素数据类型  变量   :  数组或者 Collection 集合) {
          使用变量即可, 该变量就是元素
      }
  • 普通 for 循环 , 可以删除 , 但是索引要自减 ,否则两个相同挨着的元素会漏删。
  • 迭代器,可以删除,但是必须使用迭代器自身的 remove 方法,否则会出现并发修改异常
  • 增强 for 循环 foreach 不能删除
  • 静态导入,导入类中的静态方法

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

    • 这里的变量其实是一个数组
    • 如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个
  • ( Arrays 工具类的 asList( ) 方法的使用

    • Arrays工具类的 asList() 方法的使用 ,将数组转换为集合,数组中的必需时引用数据类型,可以使用集合中的其他方法,基本数据类型的数组转换成集合,会将整个数组当做一个对象,当集合转换数组,如果数组长度小于等于 集合 size ,会自动分配,如果大于,那么就和指定的长度一致,剩下的存放空字符串。
    • Collection中 toArray ( T [ ] a ) 泛型版的集合转数组

day17 集合Set

  • 向 Set 中添加重复的元素的时候,会返回 false 。
  • HashSet 的继承体系中,有重写 toString() 方法 ,
  • Set 集合 , 无索引,不可重复,无序( 存取不一致 ) ,只要能用 迭代器 迭代的,就能使用增强 for 循环遍历。
  • 在存储中,只有两个的 hashCode 值相同,才会调用 equals 方法进行比较。否则不会调用 equals 方法进行比较。
  • 重写的 hashCode 方法 ,选择 31 的原因: 31 是一个质数,公约数少,可以降低重复率 ;1不大不小,便于计算, 31 = 2^5 -1,2向左移动五位 - 1 ,方便计算。
  • 当 HashSet 调用 add 方法的时候,先调用对象的 hashCode 方法得到一个哈希值,然后在集合中查找是否有 哈希值 相同的对象,如果有,就和 哈希值 相同的对象 逐个调用 equals 方法进行比较,结果为 true 则不存,false 就存入其中,
  • 存储自定义的 类中 必须 重写 hashCode 方法和 equals 方法:

    • hashCode 方法,属性相同的对象返回值必须相同,属性不同的对象返回值尽量不同,提高效率
    • equals 方法, 属性相同返回 true ,属性不同 返回 false ,返回 false 存储。不重写,默认按照地址值进行比较,
  • LinkedHashSet , 可以保证怎么存就怎么取,有顺序,保证存入的元素唯一,底层是 链表 实现的,是 set 中 唯一一个能保证怎么存就怎么取的集合对象。是HashSet 子类。
  • TreeSet ,可以保证元素唯一且自然排序,可以指定一个顺序,对象存入之后会按照指定的顺序排列,
  • Comparable , 可以与此对象进行比较的那些对象类型
  • ComparaTo ,比较此对象与指定对象的顺序,返回 0 ,集合中只有一个元素,返回 1 ,集合中怎么存就怎么取,返回 -1 ,倒序输出,
  • ComparaTo 底部是二叉树,小的存储在左边( 负数 ) ,大的存储在右边(正数),相等就不存(0) ,
  • 存储自定义类的时候,需要重写 comparaTo 方法,以确保可以按照顺序有序存储。
  • String 中重写的 ComparaTo 是按照字典顺序排序的,
  • TreeSet 自然排序(Comparable):

    • TreeSet 类的add () 方法会把存入的对象提升为 Comparable 类型
    • 调用对象的 compareTo() 方法和集合中的对象比较
    • 根据比较返回的结果进行存储(左边还是右边)
  • TreeSet 比较器排序(Comparator):

    • 创建 TreeSet 的时候可以制定一个 Comparator ,
    • 如果传入了 Comparator 的子类对象,那么 TreeSet 就会按照比较器中的顺序排序
    • add() 方法内部会自动调用 Comparator 接口中的 compare() 方法,
    • 调用的对象是 Compare 方法中的第一个参数,集合中的对象是 Compare 方法的第二个参数。
  • 如果构造函数什么都不传,默认按照类中 Comparable 的顺序排序,如果传入了 Comparator ,就优先按照 Comparator 来进行排序。

day18 Map集合

  • 将键映射到值的对象 ,一个映射不能包含重复的键 , 每个键最多只能映射到一个值
  • Map 接口和 Collection 接口的不同

    • Map是双列的, Collection 是单列的
    • Map的键唯一,Collection 的子体系 Set 是唯一的
    • Map 集合的数据结构值针对 键 有效,跟值无关,Collection 集合的数据结构是针对 元素 有 效
  • Map集合的功能概述

    • 添加功能

      • V put( K key , V value ):添加元素。

        • 如果键是第一次存储,就直接存储元素,返回null
        • 如果键不是第一次存在,就用值把以前的值替换掉,把被覆盖的值返回
    • 删除功能

      • void clear() :移除所有的键值对元素
      • V remove(Object key):根据键删除键值对元素,并把值返回
    • 判断功能

      • boolean containsKey ( Object key ) :判断集合是否包含指定的键
      • boolean containsValue ( Object value ) :判断集合是否包含指定的值
      • boolean isEmpty():判断集合是否为空
    • 获取功能

      • Set<Map.Entry<K,V>> entrySet():
      • V get(Object key):根据键获取值
      • Set keySet():获取集合中所有键的集合
      • Collection values() : 获取集合中所有值的集合,map.values() ,
    • 长度功能

      • int size():返回集合中的键值对的个数
  • map 集合不能通过迭代器 迭代
  • 键找值思路:

    • 获取所有键的集合
    • 遍历键的集合,获取到每一个键
    • 根据键找值
  • 键值对对象找键和值思路:

    • 获取所有键值对对象的集合
    • 遍历键值对对象的集合,获取到每一个键值对对象
    • 根据键值对对象找键和值
    • Entry 是 Map.Enter 的一个字对象
  • LinkedHashMap的特点

     * 底层是链表实现的可以保证怎么存就怎么取
    
  • 存储自定义的 类中 必须 重写 hashCode 方法和 equals 方法,才可以将其存在集合中保持集合的属性:

    • hashCode 方法,属性相同的对象返回值必须相同,属性不同的对象返回值尽量不同,提高效率
    • equals 方法, 属性相同返回 true ,属性不同 返回 false ,返回 false 存储。不重写,默认按照地址值进行比较,
  • HashMap 和 Hashtable :

    • 共同点:

      • 底层都是 哈希算法 ,都是双列集合
    • 不同点:

      • Hashtabl e是 JDK1.0 版本出现的,是线程安全的,效率低,HashMap 是 JDK1.2 版本出现的,是线程不安全的,效率高
      • Hashtable 不可以存储 null 键和 null 值 ,HashMap 可以存储 null 键和 null 值
  • Collections 常见方法:

     public static <T> void sort ( List<T>  list ) ,排序,需要实现了 
     public static <T> int binarySearch ( List<?> list , T key) ,二分查找法查找元素的索引,
     public static <T> T max ( Collection<?> coll )   , 根据字典排序结果,获取最大值
     public static void reverse ( List<?>  list ), 翻转集合

    Public static void shuffle ( List<?> list ) ,随即换,可以用来洗牌

  • 泛型固定下边界 : ? super E
  • 泛型固定下边界 : ? extends E
  • 集合总结:
  • Collection

    • List( 存取有序,有索引,可以重复 )

      • ArrayList ( 底层是数组,实现的,线程不安全,查找修改快,增删比较慢 )
      • LinkedList ( 底层是链表实现的 , 线程不安全,增删比较快,查找和修改比较慢 ,栈)
      • Vector( 底层是数组实现的,线程安全,无论增删改查都慢 )
    • 查找修改多,用 ArrayList
    • 增和删多,用 LinkedList
    • 都多,用 ArrayList
    • Set ( 存取无序,无索引,不可以重复 )

      • HashSet (底层是 哈希算法实现的)
      • LinkedHashSet ( 底层是 链表实现,但是也可以保证元素唯一,和 HashSet 原理一样 )
      • TreeSet ( 底层是二叉树算法实现 )
      • 一般开发使用不需要对存储的元素排序,所以大部分使用 HashSet ,效率较高。
      • TreeSet 面试时候用,
  • Map

    • HashMap ( 底层是 哈希算法,针对键 )
    • LinkedHashMap(底层是链表,也是针对键)
    • TreeMap (底层是二叉树算法,针对键)
    • 开发中用 HashMap 较多。
    • TreeMap 排序,面试用的多。
最后修改:2018 年 07 月 17 日
哇卡哇卡