一、Collection 集合

  • 概述
    • 集合是java中提供的一种容器,可以用来存储多个数据。
  • 集合和数组既然都是容器,它们有啥区别呢?
      • 数组的长度是固定的。集合的长度是可变的。
      • 数组中存储的是同一类型的元素,可以存储基本数据类型值。集合存储的都是对象。而且对象的类型可以不一致。在开发中一般当对象多的时候,使用集合进行存储。
  • 集合框架
    • 集合按照其存储结构可以分为两大类,分别是 单列集合 java.util.Collection 和 双列集合 java.util.Map
    • Collection 接口
      • 所有单列集合的最顶层的接口,里边定义了所有单列集合共性的方法。
      • 有两个重要的子接口,分别是 java.util.List java.util.Set 
        • List 的特点是元素有序、元素可重复。
        • Set 的特点是元素无序,切不可重复。
    • Collection 接口体系图

      

    • 任意的单列集合都可以使用 Collection 接口中的方法
      • public  boolean  add(E e)
        •  把给定的对象添加到当前集合中 。
      • public  void  clear()
        • 清空集合中所有的元素。
      • public  boolean  remove(E e)
        • 把给定的对象在当前集合中删除
      • public  boolean  contains(E e)
        • 判断当前集合中是否包含给定的对象。  
      • public  boolean  isEmpty()
        • 判断当前集合是否为空。
      • public  int  size()
        • 返回集合中元素的个数。
      • public  Object[]  toArray()
        • 把集合中的元素,存储到数组中。

 二、Iterator 迭代器

  • Iterator 接口
    • Iterator 接口也是 Java 集合中的一员,但它与 CollectionMap 接口有所不同,Collection 接口与 Map 接口主要用于存储元素,而 Iterator 主要用于迭代访问(即遍历)Collection 中的元素,因此 Iterator 对象也被称为迭代器。
    • 是一个接口,我们无法直接使用,需要使用 Iterator 接口的实现类对象。
      • 获取实现类的方式比较特殊
        • Collection 接口中有一个方法,叫 iterator(),这个方法返回的就是迭代器的实现类对象。
          • Iterator <E> iterator()
            • 返回在此 collection 的元素上进行迭代的迭代器。
        • 迭代器的使用步骤(重点)
          • 使用集合中的方法 iterator() 获取迭代器的实现类对象,使用 Iterator 接口接收(多态)。
            • Iterator <E>接口也是有泛型的,迭代器的泛型跟着集合走,集合是什么泛型,迭代器就是什么泛型。
          • 使用 Iterator 接口中的方法 hasNext() 判断还有没有下一个元素 (while) 。
          • 使用 Iterator 接口中的方法 next() 取出集合中的下一个元素。
  • 增强 for
    • 是 JDK1.5 以后出来的一个高级 for 循环,专门用来遍历数组和集合的。它的内部原理其实是个 Iterator 迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
    • 只能用来遍历集合和数组。
    • 格式
      • for(集合/数组的数据类型 变量名  :  集合名/数组名){
        • sout(变量名) ;
      • }

三、泛型

  • 作用
    • 可以在类或方法中预支地使用未知的类型。
    • 好处
      • 避免了类型转换的麻烦,存储的是什么类型,取出的就是什么类型。
      • 把运行期异常(代码运行之后会抛出的异常),提升到了编译期(写代码的时候会报错)。
    • 弊端
      • 泛型是什么类型,只能存储什么类型的数据。
  • 泛型不存在继承关系。
    • Collection<Object> list = new ArrayList<String>();
      • 这种写法是错误的。
  • 创建集合对象,不使用泛型
    • 好处
      • 集合不使用泛型,默认的类型就是 Object 类型,可以存储任意类型的数据。
    • 弊端
      • 不安全,会引发异常。
        • 发生转换异常。
  • 泛型,用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递。
      • 格式
        • 修饰符  class  类名<代表泛型的变量> {  }
      • 创建对象的时候确定泛型的数据类型。
      • 举例
        • public  class  GenericClass<E>{
          • private  E  name;
          • get/set方法;
        • }
        • 创建对象
          • 创建 GenericClass 对象,泛型使用 Integer 类型。
            • GenericClass<Integer>  gc  =  new  GenericClass<>();
          • 创建 GenericClass 对象,泛型使用 String 类型。
            • GenericClass<String>  gc2  =  new  GenericClass<>();
    • 方法
      • 定义含有泛型的方法:泛型定义在方法的修饰符和返回值类型之间。
        • 格式
          • 修饰符  <泛型>  返回值类型  方法名(参数列表(使用泛型)) {
            • 方法体
          • }
          • 含有泛型的方法,在调用方法的时候确定泛型的数据类型。
            • 传递什么类型的参数,泛型就是什么类型。
        • 举例
          • public class GenericMethod {
            • //定义一个含有泛型的方法
            • public  <M>  void  method01(M  m){}
            • //定义一个含有泛型的静态方法
            • public  static  <S>  void  method02(S  s){}
          • }
          • 使用
            • GenericMethod  gm = new  GenericMethod();
            • gm.method01(10);
            • gm.method01("abc");
              • 传递什么类型,泛型就是什么类型。
            • GenericMethod.method02("静态方法");
              • 不建议创建对象使用,通过类名.方法名(参数)可以直接使用。
    • 接口
      • 第一种使用方式
        • 定义接口的实现类,实现接口,指定接口的泛型。
          • 举例
            • Scanner 类实现了 Iterator 接口,并指定接口的泛型为String,所以重写的 next() 方法泛型默认就是 String。
              • public interface Iterator<E> {
                • E   next();
              • }
              • public  final  class  Scanner  implements  Iterator<String>{
                • public  String  next() {}
      • 第二种使用方式
        • 接口使用什么泛型,实现类就使用什么泛型,类跟着接口走。
          • 就相当于定义了一个含有泛型的类,创建对象的时候确定泛型的类型。
            • public  interface  List<E>{
              • boolean  add(E e);
              • E  get(int index);
            • }
            • public  class  ArrayList<E>  implements  List<E>{
              • public boolean add(E e) {}
              • public E get(int index) {}
            • }
  • 泛型通配符
    • 当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符 <?> 表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。
    • 通配符的基本使用
      • 不知道使用什么类型来接收的时候,此时可以使用 ?
        • ?表示未知通配符。
        • 此时只能接受数据,不能往该集合中存储数据。
    • 通配符的高级使用
      • Java 的泛型中可以指定一个泛型的上限下限
        • 泛型的上限
          • 格式
            • 类型名称 <? extends 类 > 对象名称
            • public static void getElement1(Collection<? extends Number> coll){}
              • 泛型的上限:此时的泛型?,必须是 Number 类型或者 Number 类型的子类。
          • 意义
            • 只能接收该类型及其子类。
        • 泛型的下限
          • 格式
            • 类型名称 <? super 类 > 对象名称
            • public static void getElement2(Collection<? super Number> coll){}
              • 泛型的下限:此时的泛型?,必须是 Number 类型或者 Number 类型的父类
          • 意义
            • 只能接收该类型及其父类型。

四、List 集合

  • java.util.List 接口继承自 Collection 接口,是单列集合的一个重要分支,习惯性地会将实现了 List 接口的对象称为 List 集合。在 List 集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素。另外,List 集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。

  • List 接口的特点
    • 有序的集合,存储元素和取出元素的顺序是一致的。(存储123 取出123)
    • 有索引,包含了一些带索引的方法。
    • 允许存储重复的元素。
  • List 接口中带索引的方法(特有)
    • public  void  add(int  index, E  element)
      • 将指定的元素,添加到该集合中的指定位置上。
    • public E get(int index)
      • 返回集合中指定位置的元素。
    • public E remove(int index)
      • 移除列表中指定位置的元素, 返回的是被移除的元素。
    • public E set(int index, E element)
      • 用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
  • List 集合遍历有3种方式
    • 使用普通的for循环
    • 使用迭代器
    • 使用增强for

五、LinkedList 集合

  • 集合数据存储的结构是链表结构。
  • LinkedList 集合的特点
    • 底层是一个链表结构。
      • 查询慢,增删快。
    • 里边包含了大量操作首尾元素的方法
    • 注意:使用 LinkedList 集合特有的方法,不能使用多态。
  • 常用方法
    • public void addFirst(E e)
      • 将指定元素插入此列表的开头。
    • public void addLast(E e)
      • 将指定元素添加到此列表的结尾。
    • public void push(E e)
      • 将元素推入此列表所表示的堆栈。
        • 此方法等效于 addFirst(E)。
    • public E getFirst()
      • 返回此列表的第一个元素。
    • public E getLast()
      • 返回此列表的最后一个元素。
        • 此方法等效于 add()
    • public E removeFirst()
      • 移除并返回此列表的第一个元素。
    • public E removeLast()
      • 移除并返回此列表的最后一个元素。
    • public E pop()
      • 移除并返回此列表的最后一个元素。
        • 此方法相当于 removeFirst
    • public boolean isEmpty()
      • 如果列表不包含元素,则返回true。

 六、Set 接口

  • 接口和 java.util.List 接口一样,同样继承自 Collection 接口,它与 Collection 接口中的方法基本一致,并没有对 Collection 接口进行功能上的扩充,只是比Collection 接口更加严格了。与 List 接口不同的是,Set 接口中元素无序,并且都会以某种规则保证存入的元素不出现重复。
  • Set 接口特点
    • 不允许存储重复的元素
      • 保证元素唯一性的方式依赖于:hashCode equals方法。
    • 没有索引,没有带索引的方法,也不能使用普通的 for 循环遍历。
      • 使用迭代器遍历。
      • 使用增强 for 遍历。
  • Set 集合存储元素不重复原理图

  • HastSet
    • 实现 Set 接口。
    • 特点
      • 不允许存储重复的元素。
      • 没有索引,没有带索引的方法,也不能使用普通的 for 循环遍历
      • 是一个无序的集合,存储元素和取出元素的顺序有可能不一致。
      • 底层是一个哈希表结构(查询的速度非常的快)。
    • HashSet 集合存储数据的结构

          

 

    • HashSet 存储自定义类型元素
      • 必须重写 hashCode 方法和 equals 方法。
  • LinkedHashSet
    • 保证了元素唯一。
    • 保证元素有序。
    • 特点
      • 底层是一个哈希表(数组+链表/红黑树) + 链表。
        • 多了一条链表(记录元素的存储顺序),保证元素有序。
  • 哈希值
    • 是一个十进制的整数,由系统随机给出。
      • 就是对象的地址值,是一个逻辑地址,是模拟出来得到地址,不是数据实际存储的物理地址。
        • 在Object类有一个方法,可以获取对象的哈希值。
          • int hashCode()
            • 返回该对象的哈希码值。
  • 可变参数
    • 使用前提
      • 当方法的参数列表数据类型已经确定,但是参数的个数不确定,就可以使用可变参数。
    • 格式
      • 修饰符  返回值类型  方法名(数据类型...变量名){}
    • 原理
      • 可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数。
        • 传递的参数个数,可以是0个(不传递),1,2...多个。
    • 注意事项
      • .一个方法的参数列表,只能有一个可变参数。
      • 如果方法的参数有多个,那么可变参数必须写在参数列表的末尾。

七、Collentions

  • 集合工具类,用来对集合进行操作。
    • 常用方法
      • public  static  <T>  boolean  addAll(Collection<T>  c, T... elements)
        • 往集合中添加一些元素。
      • public  static  void  shuffle(List<?>  list)
        • 打乱顺序:打乱集合顺序。
      • public  static  <T>  void  sort(List<T>  list)
        • 将集合中元素按照默认规则排序。
          • 默认升序
          • 使用前提
            • 被排序的集合里边存储的元素,必须实现 Comparable,重写接口中的方法 compareTo() 定义排序的规则。
            •  Comparable接口的排序规则
              • 自己(this)-参数
                • 升序
      • public  static <T>  void  sort(List<T>  list,Comparator<? super T> )
        • 将集合中元素按照指定规则排序。
        • 排序规则
          • o1-o2:升序
      •  Comparator 和 Comparable 的区别
        • Comparable:自己(this)和别人(参数)比较,自己需要实现 Comparable 接口,重写比较的规则 compareTo()方法。
          • 强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。只能在类中实现compareTo() 一次,不能经常修改类的代码实现自己想要的排序。实现此接口的对象列表(和数组)可以通过 Collections.sort(和Arrays.sort)进行自动排序,对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。
        • Comparator:相当于找一个第三方的裁判,比较两个。
          • 强行对某个对象进行整体排序。可以将Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用 Comparator 来控制某些数据结构(如有序 set 或有序映射)的顺序,或者为那些没有自然顺序的对象 collection 提供排序。

八、Map 

  • 概述
    • 现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号与个人。这种一一对应的关系,就叫做映射。Java 提供了专门的集合类用来存放这种对象关系的对象,即 java.util.Map 接口。
  • Map 集合的特点
    • Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)。
    • Map集合中的元素,key 和 value 的数据类型可以相同,也可以不同。
    • Map集合中的元素,key 是不允许重复的,value 是可以重复的。
    • Map集合中的元素,key 和 value 是一一对应。
    • 常用方法
      • public V put(K key, V value)
        • 把指定的键与指定的值添加到Map集合中。
          • 返回值:V
            • 存储键值对的时候,key 不重复,返回值 V 是 null。
            • 存储键值对的时候,key重复,会使用新的 value 替换 map 中重复的 value,返回被替换的 value 值。
      • public V remove(Object key)
        • 把指定的键,所对应的键值对元素,在 Map 集合中删除,返回被删除元素的值。
          • 返回值:V
            • key 存在,V 返回被删除的值。
            • key 不存在,V 返回 null 。
      • public V get(Object key)
        • 根据指定的键,在 Map 集合中获取对应的值。
          • 返回值:V
            • key存在,返回对应的 value 值。
            • key 不存在,返回 null 。
      • boolean containsKey(Object key)
        • 判断集合中是否包含指定的键。
          • 包含返回 true,不包含返回 false 。
    • Map 集合的遍历方法
      • 通过键找值的方式
        • Set<K> keySet()
          • 返回此映射中包含的键的 Set 视图。
        • 实现步骤
          • 使用 Map 集合中的方法 keySet(),把 Map 集合所有的 key 取出来,存储到一个 Set 集合中。
          • 遍历 Set 集合,获取 Map 集合中的每一个 key 。
          • 通过 Map 集合中的方法 get(key) ,通过 key 找到 value 。
      • 使用 Entry 对象遍历方式
        • Set<Map.Entry<K,V>> entrySet()
          • 返回此映射中包含的映射关系的 Set 视图。
        • 实现步骤
          • 使用 Map 集合中的方法 entrySet(),把 Map 集合中多个 Entry 对象取出来,存储到一个 Set 集合中。
          • 遍历 Set 集合,获取每一个 Entry 对象。
          • 使用 Entry 对象中的方法 getKey() 和 getValue() 获取键与值。
  • HashMap <K,V>
    • 实现 Map 接口
    • 特点
      • HashMap 集合底层是哈希表:查询的速度特别的快。
        • JDK1.8 之前:数组 + 单向链表。
        • JDK1.8 之后:数组 + 单向链表|红黑树(链表的长度超过8):提高查询的速度。
      • HashMap 集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致。
    • HashMap 存储自定义类型键值
      • 如果自定义对象作为 key 存在,必须保证对象唯一。
        • 必须复写对象的 hashCode 和 equals 方法。
    • 如果要保证 Map 中存放的 key 和取出的顺序一致,可以使用 LinkHashMap 集合来存放。
  • LinkHashMap <K,V>
    • 继承 HashMap <K,V>
    • 特点
      • LinkedHashMap 集合底层是哈希表 + 链表(保证迭代的顺序)。
      • LinkedHashMap 集合是一个有序的集合,存储元素和取出元素的顺序是一致的。

九、JDK 9 对集合的优化

  • 对 List接口,Set接口,Map接口
    • 里边增加了一个静态的方法 of,可以给集合一次性添加多个元素。
      • 格式
        • static <E> List<E> of​(E... elements)
      • 适用前提
        • 当集合中存储的元素的个数已经确定了,不在改变时使用。
      • 注意事项
        • of 方法只适用于 List 接口,Set 接口, Map 接口,不适用子接口的实现类。
        • of 方法的返回值是一个不能改变的集合,集合不能再使用 add,put 方法添加元素,会抛出异常。
        • Set 接口和 Map 接口在调用 of 方法的时候,不能有重复的元素,否则会抛出异常。

十、集合完结。

 posted on 2020-03-12 15:26  _MoLiao  阅读(211)  评论(0编辑  收藏  举报