集合(1)

本文详细介绍了集合与数组的区别,包括数组的固定长度、单一类型限制以及集合的动态扩展和对象操作便捷性。同时,分析了ArrayList作为集合实现的内部机制,包括动态扩容、元素的增删改查操作,以及遍历方式如迭代器和增强for循环。此外,还展示了List接口的常用方法和遍历策略,并通过示例代码说明了冒泡排序的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

集合的理解与好处

数组

  • 长度开始必须指定,而且一旦指定,不能改变。
  • 保存的必须为同一类型的元素
  • 使用数组进行增加/删除元素的示意代码-比较麻烦
    数组扩容方式:新建一个数组,并把旧数组元素拷贝到新数组

集合

  • 可以动态保存任意多个对象,使用比较方便
  • 提供了一系列方便的操作对象的方法:add、remove、set、get等
  • 使用集合添加,删除新元素的示意代码-简洁了

集合类图

集合主要是两组(单例集合、双例集合)
Collection 接口有两个重要的子接口 List Set 他们的实现子类都是单例集合
Map 接口的实现子类是双例集合,存放的K :V
在这里插入图片描述
Map类图
在这里插入图片描述请添加图片描述

Collection接口和常用方法

collection实现子类可以存放多个元素,每个元素可以是Object
有些collection的实现类,有些是有序的(List),有些不是有序的(set)
Collection接口没有直接的实现子类,是通过List跟Set来实现的
Collection接口遍历元素方式1-使用iterator(迭代器)
基本介绍在这里插入图片描述

 Collection arrayList = new ArrayList();
        /*add添加单个元素 当添加基本元素时会自动装箱成封装元素 int -->Integer*/
        arrayList.add("jack");
        arrayList.add(10);
        arrayList.add(true);
        System.out.println("list=" + arrayList);
        /*remove删除元素*/
        arrayList.remove(0);//删除第一个元素返回列表下标
        arrayList.remove("jack");//指定删除jack元素
        System.out.println("list=" + arrayList);
        /*contains:查找元素是否存在*/
        System.out.println(arrayList.contains(10));
        /*size:获取元素的个数*/
        System.out.println(arrayList.size());
        /*isEmpty:判断元素是否为空*/
        System.out.println(arrayList.isEmpty());
        /*clear清空*/
//        arrayList.clear();
        System.out.println(arrayList);
        /*addAll添加多个元素*/
        ArrayList arrayList1 = new ArrayList();
        arrayList1.add("红楼梦");
        arrayList1.add("红楼梦3");
        arrayList.addAll(1,arrayList1);//从第几个位置(从0开始)开始插入
        System.out.println("list=" + arrayList);
        /*containsAll查找多个元素是否都存在*/
        System.out.println(arrayList.containsAll(Collections.singleton(arrayList.containsAll(arrayList1))));
        /*removeAll  删除多个元素*/
        arrayList.add("聊斋");
        arrayList.removeAll(arrayList1);
        System.out.println("list=" + arrayList);

Iterator对象称为迭代器,主要用于遍历Collection集合中的元素
所有实现了Collection接口的集合类都有一个Iterator()方法,用以返回一个实现了Iterator接口的对象,既可以返回一个迭代器
Iterator的结构是数据结构
Iterator仅用于遍历集合,Iterator本身并不存放对象
迭代器的执行原理
Iterator Iterator = coll.iterator()//得到一个集合的迭代器
hasNext()判断是否还有下一个元素
while(iterator.hasNext()){
next(); 下移,将下移以后的集合位置上的元素返回
}

ctrl + j 查看全部快捷键
迭代器的使用

Collection collection = new ArrayList();
        collection.add(new Book("123","wzh"));
        collection.add(new Book("125","wzh1"));
        collection.add(new Book("124","wzh2"));
        /*先得到迭代器*/
        Iterator iterator = collection.iterator();
        while (iterator.hasNext()) {
            Object next =  iterator.next();
            System.out.println(next.toString());
        }
        /*当while循环退出后,迭代器指向最后一个元素,再次使用next则会爆一个没有元素的错误
        * 需要重新定义一个迭代器第二次遍历
        * */
        iterator = collection.iterator();
        while (iterator.hasNext()) {
            Object next =  iterator.next();
            System.out.println(next);

        }

增强for循环
底层是迭代器

 Collection collection = new ArrayList();
        collection.add(new Book("123","wzh"));
        collection.add(new Book("125","wzh1"));
        collection.add(new Book("124","wzh2"));
        /*增强for 底层 是迭代器  可以理解为是简化版的迭代器*/
        for (Object o : collection) {
            System.out.println(o);
        }

List接口和常用方法

List接口是Collection接口的子接口List.java
List集合类中元素有序(即添加顺序和取出顺序一致)、且可重复
List集合中的每个元素都有对应的顺序索引,即支持索引
List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素
JDK API中List接口的实现类有
在这里插入图片描述
常用的有ArrayList、LinkedList和Vector

List list = new ArrayList();
        list.add("java");
        list.add("java");
        list.add("java");
        list.add("java");
        /*void add(int index,Object Obj) 在index位置插入obj元素*/
        list.add(2,"wzh");
        System.out.println(list);
        /*boolean addAll(int index,Collection eles) 从index位置开始将eles中的所有元素添加进来*/
        List list1 = new ArrayList();
        list1.add("web");
        list1.add("web2");
        list.addAll(1,list1);
        System.out.println("list:" + list);
        /*Object get(int index) 获取指定index位置的元素*/
        System.out.println(list.get(1));
        /*int indexOf(Object obj) 返回obj在集合中首次出现的位置*/
        System.out.println(list.indexOf("java"));
        /*int lastIndexOf(Object obj) 返回obj在当前集合中最后出现的位置*/
        System.out.println(list.lastIndexOf("java"));
        //Object remove(int index) 移除指定index位置的元素,并返回此元素
        System.out.println(list.remove(1));
        System.out.println(list);
        //Object set(int index,Object obj)设置指定index位置的元素为obj,相当于替换.
        //如果index设置超过列表最大下标,则会出现IndexOutOfBoundsException
        list.set(1,"wzh");
        System.out.println(list);
        //List subList(int fromIndex,int toIndex): 返回从fromIndex到toIndex位置的子集合
        //[0,2)前闭后开
        List list2 = list.subList(0,2);
        System.out.println(list2);

List习题

 List<String> list1 = new ArrayList<String>();
        for (int i = 0;i<10;i++){
            list1.add("helloWorld"+i);
        }
        /*在第二个位置插入一个元素*/
        list1.add(1,"wzh");
        /*取到第5个元素*/
        String diwu = list1.get(5);
        System.out.println(diwu);
        /*删除第6个元素*/
        list1.remove(6);
        System.out.println(list1);
        /*修改第7个元素*/
        list1.set(6,"wzh6");
        System.out.println(list1);
        /*迭代器的方式去遍历*/
        Iterator iterator = list1.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

List接口和常用方法
List的三种遍历方式{ArrayList,LinkedList,Vector}
方式一:使用iterator

Iterator iterator = list1.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

方式二:使用增强for循环

for (String s : list1) {
            System.out.println(s);
        }

方式三:使用普通for循环

for (int i = 0;i<list1.size();i++) {
            System.out.println(list1.get(i));
        }

对书的价格进行冒泡排序,从小到大

**public static void main(String[] args) {
        List list = new ArrayList();
        list.add(new Book("12","wzh",10));
        list.add(new Book("123","wzh",20));
        list.add(new Book("124","wzh",100));
        list.add(new Book("125","wzh",60));

        for (Object o : list) {
            System.out.println(o);
        }
        sort(list);
        for (Object o : list) {
            System.out.println(o);
        }
    }
    public static void sort(List list){
        int listSize = list.size();
        for (int i = 0; i < listSize-1; i++) {
            for (int j = 0; j <listSize-1-i; j++) {
                Book book1 = (Book)list.get(j);
                Book book2 = (Book)list.get(j+1);
                if (book1.getJiage()>book2.getJiage()){
                    list.set(j,book2);
                    list.set(j+1,book1);
                }
            }
        }
    

Arraylist底层结构和源码分析

ArrayDetail.java
ArrayList可以加入null,并且可以多个
ArrayList是由数组来实现数据存储的
ArrayList基本等同于Vector,除了ArrayList是线程不安全(执行效率高)没有使用synchronized关键字,在多线程情况下,不建议使用ArrayList

线程不安全,没有使用synchronized
public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

ArrayList的底层操作机制:
ArrayListSource.java
ArrayList中维护看一个Object类型的数组elementData、transient Object[] elementData transient 表示瞬间的短暂的、表示该属性不会被序列化(变成二进制)
在这里插入图片描述

当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如果需要再次扩容,则扩容elementData为1.5倍

创建了一个空的elementData数组 = {}
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

//执行list.add
//先确定是否要扩容
//然后在执行 赋值


public boolean add(E e) {
		//判断空间是否足够
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

//该方法确定minCapacity
//第一次扩容为10


//
private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

如果elementData的大小不够,就调用grow()去扩容


 private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//记录当前集合被修改的次数

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

真的扩容
使用扩容机制来确定要扩容到多大
第一次newCapacity = 10
第二次及其以后,按照1.5倍扩容
扩容使用的是Arrays.copyOf()

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值