• 06.集合


    一、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 方法的时候,不能有重复的元素,否则会抛出异常。

    十、集合完结。

  • 相关阅读:
    网页中插入Flash动画(.swf)代码和常用参数设置
    关于UML中逻辑模型的工具的详细介绍
    简单CSS hack:区分IE6、IE7、IE8、Firefox、Opera
    mysql sock找不到
    简述nginx日志管理切割日志(亲测可行)
    Linux下使用rm删除文件,并排除指定文件(亲测可行)
    常驻内存以及如何避免内存泄漏
    TASK异步进程处理场景
    TCP长连接数据传输(同步方式)
    在智联上投了一个月的简历,很多都有意向,但是却没有通知我去
  • 原文地址:https://www.cnblogs.com/_Moliao/p/12462487.html
Copyright © 2020-2023  润新知