java集合(超详细),Java集合详解(超全面解析)

马肤

温馨提示:这篇文章已超过414天没有更新,请注意相关的内容是否还可用!

摘要:本文详细介绍了Java集合框架,包括其基本概念、主要组成部分和常用集合类型。文章深入解析了Java集合框架中的核心接口和类,如List、Set、Map等,并探讨了它们的特性和使用场景。文章还介绍了Java集合框架的优势和重要性,以及在实际开发中的应用方法和注意事项。本文旨在为开发者提供Java集合框架的全面指南,帮助更好地理解和运用Java集合。

1 - 概述

        所有的集合类和集合接口都在java.util包下。

        在内存中申请一块空间用来存储数据,在Java中集合就是替换掉定长的数组的一种引用数据类型。

2 - 集合与数组的区别

长度区别

        数组长度固定,定义长了造成内存空间的浪费,定义短了不够用。

        集合大小可以变,用多少空间拿多少空间。

内容区别

        数组可以存储基本数据类型和引用数据类型

        集合中能存储引用数据类型(存储的为对象的内存地址)

       list.add(100);//为自动装箱,100为Integer包装的

元素区别

        数组中只能存储同一种类型成员

        集合中可以存储不同类型数据(一般情况下也只存储同一种类型的数据)

集合结构

        在java中每一个不同的集合,底层会对应不同的数据结构。往不同的集合中

    存储元素,等于将数据放到了不同的数据结构当中。什么是数据结构?数据存储的

    结构就是数据结构。不同的数据结构,数据存储方式不同。

  • 单列集合 Collection

    • List可以重复:ArrayList/LinkedList

    • Set不可重复:HashSet/TreeSet

    • java集合(超详细),Java集合详解(超全面解析) 第1张


      (大量文字插入会导致图片不清,所以在此进行更详细的描述)

    • List特点:此处顺序并不是大小顺序,而是存入数据的先后顺序。有序因为List集合都有下标,下标从0开始,以递增。

    • Set特点:取出顺序不一定为存入顺序,另外Set集合没有下标。

    • ArrayList是非线程安全的。

    • HashSet集合在new的时候,底层实际上new了一个HashMap集合。向HashSet集合中存储元素,实际上是存储到了HashMap的key中了。HashMap集合是一个Hash表数据结构。

    • SortedSet集合存储元素的特点:由于继承了Set集合,所以他的特点也是无序不可重复,但是放在SortedSet集合中的元素可以自动排序。放到该集合中的元素是自动按照大小顺序排序的。

    • TreeSet集合底层实际上是TreeMap。TreeSet集合在new的时候,底层实际上new了一个TreeMap集合。向TreeSet集合中存储元素,实际上是存储到了TreeMap的key中了。TreeMap集合是一个二叉树数据结构。

  • 双列集合Map:HashMap/TreeMap

    java集合(超详细),Java集合详解(超全面解析) 第2张

    粗体是接口 斜体是实现类

    3 - Collection集合

    3.1 - 概述

    单列集合的顶层接口,既然是接口就不能直接使用,需要通过实现类!~

    3.2 - Collection集合的的常用方法

    方法名说明
    boolean add(E e)添加元素到集合的末尾(追加)
    boolean remove(Object o)删除指定的元素,成功则返回true(底层调用equles)
    void clear()清空集合
    boolean contains(Object o)判断元素在集合中是否存在,存在则返回true(底层调用equles)
    boolean isEmpty()判断集合是否为空,空则返回true
    int size()返回集合中元素个数
    import java.util.ArrayList;
    import java.util.Collection;
    /**
     * @author Mr.乐
     * @Description
     */
    public class Collection_01 {
        public static void main(String[] args) {
            //父类的引用指向子类的对象,形成多态
            Collection con = new ArrayList();
            //追加的方式添加元素
            con.add("东邪");
            con.add("西毒");
            con.add("南帝");
            con.add("北丐");
            con.add("中神通");
            //删除,通过元素名称删除元素
            System.out.println(con.remove("西毒"));
            //判断集合中是否包含指定参数元素
            System.out.println(con.contains("西毒"));  //false
            System.out.println(con.contains("东邪"));    //true
            //获取集合中元素个数
            System.out.println(con.size());
            //判断是否为空
            System.out.println(con.isEmpty());//false
            //清空集合
            con.clear();
            //判断是否为空
            System.out.println(con.isEmpty());//true
            System.out.println(con);//打印集合的元素
        }
    }

    3.3 - Collection集合的遍历

            以下迭代方式,是所有Collection通用的一种方式。在Map集合中不能使用,在所有的Collection以及子类中使用。

    java集合(超详细),Java集合详解(超全面解析) 第3张

    java集合(超详细),Java集合详解(超全面解析) 第4张

    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    /**
     * @author Mr.乐
     * @Description  Collection 集合的遍历
     */
    public class Connection_02 {
        public static void main(String[] args) {
            //多态
            Collection con = new ArrayList();
            //添加元素
            con.add("abc");
            con.add("def");
            con.add("100");
            con.add("444");
            //Collection集合的遍历方式
            //因为没有索引的概念,所以Collection集合不能使用fori进行遍历
            //增强版for循环,其实底层使用的也是迭代器,在字节码文件中查看
            for (String str : con) {
                System.out.print(str + "\t");
            }
            System.out.println();//换行
            //迭代器,集合专属的遍历工具
            Iterator it = con.iterator();//创建迭代器对象
            while (it.hasNext()){//判断下一个位置是否有元素
                System.out.print(it.next() + "\t");//获取到下一个位置的元素
            }
        }
    }
    

    3.4 -  Iterator的remove

    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    /**
     * @author Mr.乐
     * @Description
     */
    public class Connection_remove {
        public static void main(String[] args) {
            // 创建集合
            Collection c = new ArrayList();
            // 注意:此时获取的迭代器,指向的是那是集合中没有元素状态下的迭代器。
            // 一定要注意:集合结构只要发生改变,迭代器必须重新获取。
            // 当集合结构发生了改变,迭代器没有重新获取时,调用next()方法时:java.util.ConcurrentModificationException
            Iterator it = c.iterator();
            // 添加元素
            c.add(1); // Integer类型
            c.add(2);
            c.add(3);
            // 获取迭代器
            //Iterator it = c.iterator();
            /*while(it.hasNext()){
                // 编写代码时next()方法返回值类型必须是Object。
                // Integer i = it.next();
                Object obj = it.next();
                System.out.println(obj);
            }*/
            Collection c2 = new ArrayList();
            c2.add("abc");
            c2.add("def");
            c2.add("xyz");
            Iterator it2 = c2.iterator();
            while(it2.hasNext()){
                Object o = it2.next();
                // 删除元素
                // 删除元素之后,集合的结构发生了变化,应该重新去获取迭代器
                // 但是,循环下一次的时候并没有重新获取迭代器,所以会出现异常:java.util.ConcurrentModificationException
                // 出异常根本原因是:集合中元素删除了,但是没有更新迭代器(迭代器不知道集合变化了)
                //c2.remove(o); // 直接通过集合去删除元素,没有通知迭代器。(导致迭代器的快照和原集合状态不同。)
                // 使用迭代器来删除可以吗?
                // 迭代器去删除时,会自动更新迭代器,并且更新集合(删除集合中的元素)。
                it2.remove(); // 删除的一定是迭代器指向的当前元素。
                System.out.println(o);
            }
            System.out.println(c2.size()); //0
        }
    }
    

    4 -List

    原型ArrayList

    • ArrayList是一个List接口的实现类,底层使用的是一个可以调整大小的数组实现的。

    • :是一种特殊的数据类型(引用数据类型) -- 泛型

      • ArrayList 或者 ArrayList 或者 ArrayList

      4.1 - ArrayList构造和添加方法

      方法名说明
      public ArrayList()创建一个空集合
      public boolean add(E e)将指定的参数元素追加到集合的末尾
      public void add(int index ,E e)在集合的指定位置添加指定的元素(插入元素)
      public void addAll(E object)用于将指定集合中所有元素添加到当前集合中
      /**
       * @author Mr.乐
       * @Description  ArrayList构造和添加方法
       */
      public class ArrayList_01 {
          public static void main(String[] args) {
              //创建空集合
              ArrayList list = new ArrayList();//泛型定义为String
              //采用默认追加的方式添加元素
              System.out.println(list.add("刘德华"));
              System.out.println(list.add("张学友"));
              System.out.println(list.add("郭富城"));
              System.out.println(list.add("黎明"));
              //插入的方式添加元素
      //        list.add(10,"谭咏麟");//插入元素方法索引值不能大于集合中元素个数
      //        list.add(4,"谭咏麟");//表示在集合中最后位置插入元素,与追加相同
              list.add(1,"谭咏麟");//指定位置插入元素,索引位置之后的元素会自动向后进行移动
              ArrayList newList = new ArrayList();//创建新的集合
              newList.add("小沈阳");
              newList.add("宋小宝");
              newList.add("赵四");
              newList.add("刘能");
              //查看集合中的元素
              System.out.println("原集合内部元素:" + list);
              System.out.println("新集合内部元素:" + newList);
              list.addAll(newList); //将新集合全部元素添加到原集合中
              System.out.println("原集合内部元素:" + list);
          }
      }
      

      4.2 - ArrayList集合常用方法

      方法名说明
      public boolean remove(Object o)删除指定的元素,成功则返回true
      public E remove(int index)删除指定索引位置的元素,返回被删除的元素
      public E set(int index,E e)修改指定索引位置的元素,返回修改前的元素
      public E get(int index)获取指定索引对应的元素
      public int size()获取结合中元素个数
      import java.util.ArrayList;
      import java.util.Iterator;
      /**
       * @author Mr.乐
       * @Description   ArrayList集合常用方法
       */
      public class ArrayList_02 {
          public static void main(String[] args) {
              ArrayList list = new ArrayList();
              //追加方式添加元素
              list.add("东邪");
              list.add("西毒");
              list.add("南帝");
              list.add("北丐");
              list.add("中神通");
              //删除
              System.out.println(list.remove("西毒"));//通过元素名称删除,返回boolean
              System.out.println(list.remove(1));//通过索引删除元素,返回被删除元素名
              //修改
              System.out.println(list.set(1,"西毒"));//指定索引位置修改元素,并返回被修改元素
              System.out.println("原集合中元素有:" + list);
              //获取方法
              System.out.println(list.get(1));//通过指定索引位置获取集合元素
              //获取集合元素个数
              System.out.println(list.size());
              //集合的遍历,普通for循环
              for (int i = 0; i  
      

      4.3 -ArrayList实现原理

      底层代码:

              属性:

      DEFAULT_CAPACITY = 10 默认长度,初始化容量为10
      Object[] EMPTY_ELEMENTDATA = {} //有参构造所创建
      Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {} //无参构造所创建的
      Object[] elementData;底层为Object类型的数组,存储的元素都在此。
      int size 实际存放的个数
      

               构造方法 :

      //一个参数的构造
      public ArrayList(int initialCapacity) {
              if (initialCapacity > 0) {
                  this.elementData = new Object[initialCapacity];
              } else if (initialCapacity == 0) {
                  this.elementData = EMPTY_ELEMENTDATA;
              } else {
                  throw new IllegalArgumentException("Illegal Capacity: "+
      initialCapacity);
              }
          }
      //参数如果大于零,则为创建数组的长度;
      //参数如果等于零,EMPTY_ELEMENTDATA;
      //参数如果小于0,抛出异常。
      //无参构造
        public ArrayList() {
              this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
          }
      //DEFAULTCAPACITY_EMPTY_ELEMENTDATA  new对象时默认为0 当添加第一个元素的时候,数组扩容至10

              add方法源码:(jdk1.8与之不同,此处为jdk16)

      //源码
      public boolean add(E e) {
              modCount++;//操作次数
              add(e, elementData, size);
      //e 操作对象;  elementData 底层操作的数组;size 默认大小0
              return true;
          }
      ------------------------------------------------
       private void add(E e, Object[] elementData, int s) {
              if (s == elementData.length)//ture
                  elementData = grow();
              elementData[s] = e;  //存数据
              size = s + 1; //最小需要长度
          }
      ----------------------------------------------------------
       private Object[] grow() {
              return grow(size + 1);
          }
      -----------------------------------------------------
       private Object[] grow(int minCapacity) { //初始传入为size+1  为1
              int oldCapacity = elementData.length; //初始为0
              if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
             //if条件为初始数组长度>0或者数组不是无参构造构建的
                  int newCapacity = ArraysSupport.newLength(oldCapacity, //旧数组的长度
                          minCapacity - oldCapacity, /* minimum growth */  
                          //最小需要长度-旧数组的长度  大于0代表空间不足
                          oldCapacity >> 1           /* preferred growth */);
                         //二进制位右移1位  位旧数组长度/2
                  return elementData = Arrays.copyOf(elementData, newCapacity);
                  将数据放入新数组中
              } else {
                  return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
                  //数组长度  DEFAULT_CAPACITY为10  此处代表无参构造默认长度为10
              }
          }
      ----------------------------------------------------
       public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
              // assert oldLength >= 0
              // assert minGrowth > 0
                
              int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
               //如果prefGrowth>minGrowth  扩容1.5倍    minGrowth>prefGrowth为需要多少给多少
              if (newLength - MAX_ARRAY_LENGTH  20 --> 40 --> 80
      4、Vector中所有的方法都是线程同步的,都带有synchronized关键字,
      是线程安全的。效率比较低,使用较少了。
      5、怎么将一个线程不安全的ArrayList集合转换成线程安全的呢?
          使用集合工具类:
              java.util.Collections;
              java.util.Collection 是集合接口。
              java.util.Collections 是集合工具类。
      Collections.synchronizedList();//将及格转换为线程安全的。

      5 -Set

      5.1 -概述

      • Set集合也是一个接口,继承自Collection,与List类似,都需要通过实现类来进行操作

      • 特点

        • 不允许包含重复的值

        • 没有索引(就不能使用普通的for循环进行遍历)

        import java.util.HashSet;
        import java.util.Set;
        /**
         * @author Mr.乐
         * @Description Set集合
         */
        public class Demo01 {
            public static void main(String[] args) {
                //使用多态,父类的引用指向子类对象
                Set set = new HashSet();
                //添加元素
                set.add("黄固");
                set.add("欧阳锋");
                set.add("段智兴");
                set.add("洪七公");
                set.add("段智兴");
                System.out.println(set);//打印集合
                 //[洪七公, 黄固, 欧阳锋, 段智兴]
                //HashSet集合对于元素的读写顺序不做保证
                //相同的元素,多次存储,只能保留一个,并且不会报错
                //List集合可以存储重复元素,Set集合不行
            }
        }
        

                 例:双色球

        import java.util.Random;
        import java.util.TreeSet;
        /**
         * @author Mr.乐
         * @Description  双色球 -Set版
         */
        public class Demo02 {
            public static void main(String[] args) {
                Random ran = new Random();//创建随机类对象
                int blueBall = ran.nextInt(16) + 1;
        //        HashSet redBalls = new HashSet();//创建集合用来存储红球
                TreeSet redBalls = new TreeSet();//TreeSet集合自带排序规则
                while (redBalls.size()  
        

        5.2 -哈希值

                Set集合的去重原理使用的是哈希值。

        哈希值就是JDK根据对象地址 或者 字符串 或者数值 通过自己内部的计算出来的一个整数类型数据

        public int hashCode() - 用来获取哈希值,来自于Object顶层类

        • 对象的哈希值特点

          • 同一个对象多次调用hashCode()方法,得到的结果是相同的。

          • 默认情况下,不同的对象的哈希值也是不同的(特殊情况除外)

          /**
           * @author Mr.乐
           * @Description  哈希值
           */
          public class Demo03 {
              public static void main(String[] args) {
                  //相同对象哈希值相同
                  System.out.println("张三".hashCode());//774889
                  System.out.println("张三".hashCode());//774889
                  //不同对象哈希值不同
                  System.out.println(new Object().hashCode());
                  System.out.println(new Object().hashCode());
                  //不同的对象的哈希值也有可能相同,例外情况
                  System.out.println("辂鹅".hashCode());//1179395
                  System.out.println("较鸦".hashCode());//1179395
                  System.out.println("辄鸇".hashCode());//1179395
                  System.out.println("辅鷨".hashCode());//1179395
              }
          }

          5.3 -HashSet去重原理

          • HashSet集合的特点

            • 底层结构是“哈希表”

            • 集合对于读写顺序不做保证

            • 没有索引

            • Set集合中的内容不能重复

            /**
             * @author Mr.乐
             * @Description  HashSet去重原理
             */
            public class Demo04 {
                public static void main(String[] args) {
                    HashSet set = new HashSet();
                    //添加元素
                    set.add(new Student("黄固",28));
                    set.add(new Student("欧阳锋",38));
                    set.add(new Student("段智兴",48));
                    set.add(new Student("洪七公",40));
                    set.add(new Student("段智兴",48));
                    //从程序的角度来考虑,两个段智兴不是同一个对象,都有自己的存储空间,所以哈希值也不一样。
                    for (Student stu : set) {
                        System.out.println(stu);
                    }
                    /*
                    重写hashcode和equals
                    Student{name='段智兴', age=48}
                    Student{name='欧阳锋', age=38}
                    Student{name='洪七公', age=40}
                    Student{name='黄固', age=28}
                     */
                }
            }

            5.4 -LinkedHashSet

            • 特点

              • LinkedHashSet是哈希表和链表实现的Set接口,具有可预测的读写顺序。

              • 有链表来保证元素有序

              • 有哈希表来保证元素的唯一性

              /**
               * @author Mr.乐
               * @Description LinkedHashSet
               */
              public class Demo05 {
                  public static void main(String[] args) {
                      LinkedHashSet set = new LinkedHashSet();
                      //添加元素
                      set.add("黄固");
                      set.add("欧阳锋");
                      set.add("段智兴");
                      set.add("洪七公");
                      set.add("段智兴");//重复的元素不能存进去
                      System.out.println(set);//打印集合 [黄固, 欧阳锋, 段智兴, 洪七公]
                  }
              }
              

              5.5 -TreeSet

              1、TreeSet集合底层实际上是一个TreeMap

              2、TreeMap集合底层是一个二叉树。

              3、放到TreeSet集合中的元素,等同于放到TreeMap集合key部分了。

              4、TreeSet集合中的元素:无序不可重复,但是可以按照元素的大小顺序自动排序。

              import java.util.TreeSet;
              public class TreeSetTest02 {
                  public static void main(String[] args) {
                      // 创建一个TreeSet集合
                      TreeSet ts = new TreeSet();
                      // 添加String
                      ts.add("zhangsan");
                      ts.add("lisi");
                      ts.add("wangwu");
                      ts.add("zhangsi");
                      ts.add("wangliu");
                      // 遍历
                      for(String s : ts){
                          // 按照字典顺序,升序!
                          System.out.println(s);
                      }
                      /*
                      lisi
                       wangliu
                       wangwu
                       zhangsan
                       zhangsi
                       */
                      TreeSet ts2 = new TreeSet();
                      ts2.add(100);
                      ts2.add(200);
                      ts2.add(900);
                      ts2.add(800);
                      ts2.add(600);
                      ts2.add(10);
                      for(Integer elt : ts2){
                          // 升序!
                          System.out.println(elt);
                      }
                  }
              }

              5.5.1 -自定义排序规则  

              对于自定义的类无法排序,因为类中对象之间没有比较规则,不知道谁大谁小。

              /**
               * @author Mr.乐
               * @Description  自定义比较器
               */
              import java.util.TreeSet;
              public class TreeSetTest04 {
                  public static void main(String[] args) {
                      Customer c1 = new Customer(32);
                      Customer c2 = new Customer(20);
                      Customer c3 = new Customer(30);
                      Customer c4 = new Customer(25);
                      // 创建TreeSet集合
                      TreeSet customers = new TreeSet();
                      // 添加元素
                      customers.add(c1);
                      customers.add(c2);
                      customers.add(c3);
                      customers.add(c4);
                      // 遍历
                      for (Customer c : customers){
                          System.out.println(c);
                      }
                  }
              }
              // 放在TreeSet集合中的元素需要实现java.lang.Comparable接口。
              // 并且实现compareTo方法。equals可以不写。
              class Customer implements Comparable{
                  int age;
                  public Customer(int age){
                      this.age = age;
                  }
                  // 需要在这个方法中编写比较的逻辑,或者说比较的规则,按照什么进行比较!
                  // k.compareTo(t.key)
                  // 拿着参数k和集合中的每一个k进行比较,返回值可能是>0 

0
收藏0
文章版权声明:除非注明,否则均为VPS857原创文章,转载或复制请以超链接形式并注明出处。

相关阅读

  • 【研发日记】Matlab/Simulink自动生成代码(二)——五种选择结构实现方法,Matlab/Simulink自动生成代码的五种选择结构实现方法(二),Matlab/Simulink自动生成代码的五种选择结构实现方法详解(二)
  • 超级好用的C++实用库之跨平台实用方法,跨平台实用方法的C++实用库超好用指南,C++跨平台实用库使用指南,超好用实用方法集合,C++跨平台实用库超好用指南,方法与技巧集合
  • 【动态规划】斐波那契数列模型(C++),斐波那契数列模型(C++实现与动态规划解析),斐波那契数列模型解析与C++实现(动态规划)
  • 【C++】,string类底层的模拟实现,C++中string类的模拟底层实现探究
  • uniapp 小程序实现微信授权登录(前端和后端),Uniapp小程序实现微信授权登录全流程(前端后端全攻略),Uniapp小程序微信授权登录全流程攻略,前端后端全指南
  • Vue脚手架的安装(保姆级教程),Vue脚手架保姆级安装教程,Vue脚手架保姆级安装指南,Vue脚手架保姆级安装指南,从零开始教你如何安装Vue脚手架
  • 如何在树莓派 Raspberry Pi中本地部署一个web站点并实现无公网IP远程访问,树莓派上本地部署Web站点及无公网IP远程访问指南,树莓派部署Web站点及无公网IP远程访问指南,本地部署与远程访问实践,树莓派部署Web站点及无公网IP远程访问实践指南,树莓派部署Web站点及无公网IP远程访问实践指南,本地部署与远程访问详解,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南。
  • vue2技术栈实现AI问答机器人功能(流式与非流式两种接口方法),Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法探究,Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法详解
  • 发表评论

    快捷回复:表情:
    评论列表 (暂无评论,0人围观)

    还没有评论,来说两句吧...

    目录[+]

    取消
    微信二维码
    微信二维码
    支付宝二维码