单列集合(一)

一.单列集合

1.概览     

        Java 集合,也叫作容器,主要是由两大接口:一个是 Collecion接口,主要用于存放单一元素;另一个是 Map 接口,主要用于存放键值对.Collection是单列集合的根接口,Collection接口下面又有三个子接口List接口、Set接口和Queue接口,他们下面分别有不同的实现类,如下图所示:

 

 Java 单列集合框架概览

注:图中只列举了主要的继承派生关系,并没有列举所有关系。比方省略了AbstractList, NavigableSet等抽象类以及其他的一些辅助类

2. List, Set, Queue三种集合的区别

List系列集合:存储的元素是有序,可重复,有索引的

Set系列集合:存储的元素是无序,不可重复,无索引的

Queue系列集合: 按特定的排队规则来确定先后顺序,存储的元素是有序的、可重复的.

3.了解List

List集合下有三个实现类

  • ArrayListObject[] 数组
  • VectorObject[] 数组
  • LinkedList:双向链表(JDK1.6 之前为循环链表,JDK1.7 取消了循环)
3.1List集合的常见方法

我们直接用代码演示一下


List<String> list = new ArrayList<>();
//1.boolean add(E e): 添加元素
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六"); 
System.out.println(list); //[张三, 李四, 王五, 赵六]

//2.void add(int index, E element): 在某个索引位置插入元素
list.add(2, "钱七");
System.out.println(list); //[张三, 李四,钱七, 王五, 赵六]

//3.E remove(int index): 根据索引删除元素, 返回被删除的元素
System.out.println(list.remove(2)); //钱七
System.out.println(list);//[张三, 李四, 王五, 赵六]

//4.E get(int index): 返回集合中指定位置的元素
System.out.println(list.get(3)); //赵六

//5. E set(int index, E element): 修改索引位置处的元素,修改后,会返回原数据
System.out.println(list.set(3,"老八")); //赵六
System.out.println(list); //[张三, 李四, 王五, 老八]
3.2List集合的遍历方式

List集合遍历方式一共有四种:

  • 普通for循环

  • 迭代器

  • 增强for

  • Lambda表达式

还是用代码演示一下

List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");

//1.普通for循环
for(int i = 0; i< list.size(); i++){
    //i = 0, 1, 2
    String e = list.get(i);
    System.out.println(e);
}

//2.增强for遍历
for(String s : list){
    System.out.println(s);
}

//3.迭代器遍历
Iterator<String> it = list.iterator();
while(it.hasNext()){
    String s = it.next();
    System.out.println(s);
}

//4.lambda表达式遍历
list.forEach(s->System.out.println(s));
3.3ArrayList集合的底层原理
        3.3.1ArrayList 和 Array的区别

        ArrayList集合底层是基于数组结构实现的,也就是说当你往集合容器中存储元素时,底层本质上是往数组中存储元素. 那么ArrayList 和 Array(数组)的有区别么,我们带着这个问题来深入探索ArrayList集合.

         ArrayList内部基于动态数组实现,比 Array(静态数组) 使用起来更加灵活:

  • ArrayList会根据实际存储的元素动态地扩容或缩容,而 Array 被创建之后就不能改变它的长度了。
  • ArrayList 允许你使用泛型来确保类型安全,Array 则不可以。
  • ArrayList 中只能存储对象。对于基本类型数据,需要使用其对应的包装类(如 Integer、Double 等)。Array 可以直接存储基本类型数据,也可以存储对象。
  • ArrayList 支持插入、删除、遍历等常见操作,并且提供了丰富的 API 操作方法,比如 add()remove()等。Array 只是一个固定长度的数组,只能按照下标访问其中的元素,不具备动态添加、删除元素的能力。
  • ArrayList创建时不需要指定大小,而Array创建时必须指定大小。

下面是二者使用的简单对比:

        // 初始化一个 String 类型的数组
        String[] arr = new String[]{"张三", "李四", "王五"};
        // 修改数组元素的值
        arr[0] = "赵六";
        System.out.println(Arrays.toString(arr));// [赵六, 李四, 王五]
        // 删除数组中的元素,需要手动移动后面的元素
        for (int i = 0; i < arr.length - 1; i++) {
            arr[i] = arr[i + 1];
        }
        arr[arr.length - 1] = null;
        System.out.println(Arrays.toString(arr));// [李四, 王五, null]

        // 初始化一个 String 类型的 ArrayList
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll( list,"张三","李四", "王五");
        // 添加元素到 ArrayList 中
        list.add("赵六");
        System.out.println(list);// [张三, 李四, 王五, 赵六]
        // 修改 ArrayList 中的元素
        list.set(0, "钱七");
        System.out.println(list);// [钱七, 李四, 王五, 赵六]
        // 删除 ArrayList 中的元素
        list.remove(0);
        System.out.println(list); // [李四, 王五, 赵六]
        3.3.2ArrayList的特点及底层

        ArrayList的特点是查询快,增删慢. ArrayList可以直接通过索引定位到数据位置,查询任意数据的耗时是相同的,但是在增删数据时,需要将增删元素索引位置后的所有元素都依次向前或后移动一个位置,理论耗时就会很长.

       前面通过对比得知,数组的长度是固定的,但是集合的长度是可变的,原理如下:

  • 1.利用无参构造器创建集合,会在底层创建一个默认长度为0的数组        
  • 2.添加第一个元素时,底层会创建一个新的长度为10的数组
  • 3.存满时,会扩容1.5倍
  • 4.如果一次添加多个元素,1.5倍扩容依然放不下,则新创建的数组的长度以实际为准
  • 5.我们需要注意的是,数组扩容,并不是在原数组上扩容(原数组是不可以扩容的),底层是创建一个新数组,然后把原数组中的元素全部复制到新数组中去
3.4 LinkedList集合的底层原理

        LinkedList集合的底层数据结构是双链表,特点是查询慢,增删快.操作首尾元素,查询也不慢.双向链表在存储数据时会将每一个不同的数据存储在不同的结点中,每个节点又分为三个部分,第一部分用来存储前一个结点的地址值,第二部分存储具体数据的值,第三部分则用来存储下一个节点的地址值.

        因此在使用LinkedList集合查询数据时,就相当于遍历集合查询,会从头节点开始访问,沿着链表的结构找下一个结点查询,知道找到所需要的数据才会停止.而增删数据,以新增数据为例,只需要将新增结点的上一个结点记录的下一个结点的地址值改为新增结点的地址值,再将新增结点的下一个结点,它记录的上一个结点的地址值改为新增结点的地址值即可.

        

      flag:  以后会再出源码分析相关文章,配合图文讲解,更容易理解.

     
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值