五段斗之气--Collection的子接口:List接口

        修炼完这一篇秘籍,你就可以成为五段斗之气战士了,天赋出色者甚至可以越阶战斗,成为百里挑一的斗者,踏上漫漫强者路,拳打北山幼儿园,脚踢南海敬老院。

该系列文章上一篇: 五段斗之气–Collection的子接口:List接口.
该系列文章下一篇: 六段斗之气–Collection的子接口:Set接口.


初遇List接口

  • 鉴于Java中数组用来存储数据的局限性,我们通常使用List替代数组。
  • List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。
  • List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
  • JDK API中List接口的常用实现类包括:ArrayLisr、LinkedList和Vector。

        先大体说一下ArrayList、LinkedList、Vector三个实现类之间有什么异同点。

  • 相同点:三者都是List接口的子接口,存储的数据都是有序的,可重复的。
  • 不同点:ArrayList–线程不安全,效率高,底层结构是数组,使用频率最高,大量随机访问时速度快。
    LinkedList–线程不安全,效率高,底层结构是双向链表,频繁插入、删除元素时速度更快。
    Vector–远古实现类,廉颇老了,被ArrayList代替了。线程安全,效率低,底层结构是数组。

        疑问:如果想用ArrayList,但是又想要线程安全的怎么办呢?带着这个疑问继续修炼吧。有道友可能不太理解线程安全是什么意思,觉得不好记忆,难以理解。实际上线程安全就是说有两个线程对一份数据共享,假设线程A在对该数据遍历的时候线程B把数据给改了,这样线程A如何知道线程B已经插了一脚进来了呢,两个线程如何通信呢,我们要怎样确保我们读到的数据真正是实时的数据呢,这其实就是线程安全的问题。多线程问题实际上也是Java中又一大重要的武功体系,它负责的就是数据处理这一块的问题,可以大体的认为,集合存储数据,线程处理数据,IO流传输数据,这都是我们修炼道路上的重要关卡。


List接口常用方法

        在具体修炼三个实现类之前呢,我们可以看下它们共有的行为规范有哪些,也就是是List接口的常用方法。List接口作为Collection的子接口,除了从Collection集合继承的方法外,List集合里添加了一些根据索引来操作集合元素的方法。

方法声明方法作用解释
void add(int index, Object ele)在index位置插入ele元素
boolean addAll(int index, Collection eles)从index位置开始将eles中的所有元素添加进来
Object get(int index)获取指定索引位置的元素
int indexOf(Object obj)返回该对象在集合中首次出现的位置
int lastIndexOf(Object obj)返回该对象在当前集合中末次出现的位置
Object remove(int index)移除指定Index位置的元素,并返回此元素
Object set(int index, Object ele)设置指定index位置的元素为ele
List subList(int fromIndex, int toindex)返回从fromIndex到toIndex位置的子集合

List接口实现类之ArrayList

        ArrayList是一种底层结构用数组实现的List接口实现类,它有个洋气的名字叫动态数组

ArrayList的体貌特征
  • ArrayList是List接口的典型实现类、主要实现类,提供了基础的添加、删除、遍历等操作,本质上,ArrayList是对象引用的一个“变长”数组。
  • ArrayList的JDK1.8之前与之后的实现区别?
        JDK1.7:ArrayList像饿汉,着急着慌,在你new对象的时候直接创建一个初始用量为10的数组
        JDK1.8:ArrayList像懒汉,一开始创建一个长度为0的数组,直到你添加第一个元素的时候它才
                会不慌不忙的去创建一个初始容量为10的数组。
  • Array.asList(…)方法返回的List集合,既不是ArrayList实例,也不是Vector实例。Arrays.asList(…)返回值是一个固定长度的List集合,观察Arrays类源码可以知道它返回的集合实际上其内部类的对象实例,只能进行读取操作,不能进行写操作。
ArrayList的底层源码分析:

        ArrayList和HashMap是集合内容中的重中之重,它们的源码分析也是高频热点,实际上搞清楚了这两个实现类的源码,基本上其它的也就一通百通了,因此这里会对ArrayList的源码进行抽丝剥茧般的分析,脱光它的衣服,揭开它神秘的外纱。修炼的思路是先介绍该类的属性,也就是成员变量;然后将一些重要的方法列出来进行注释讲解;最后理清该实现类工作的逻辑线,这样就基本具备成为了五段斗之气巅峰的实力,冲鸭!(代码展示以JDK1.8的为准,但是会详细说明和JDK1.7的差别有哪些)

类的声明

        打开JDK1.8中ArrayList类的源码,观察该类的方法声明,可以大概了解ArrayList有一些什么作用。
ArrayList类的声明

  • ArrayList实现了List, RandomAccess, Cloneable, java.io.Serializable等接口。
  • ArrayList实现了List,提供了基础的添加、删除、遍历等操作。
  • ArrayList实现了RandomAccess,提供了随机访问的能力。
  • ArrayList实现了Cloneable,可以被克隆。
  • ArrayList实现了Serializable,可以被序列化。
类的成员变量
    private static final long serialVersionUID = 8683452581122892189L;

    /**
     * Default initial capacity.
     * 默认初始容量
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * Shared empty array instance used for empty instances.
     * 空的初始数组,创建指定了初始容量大小集合时使用
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     * 没有给定初始容量大小,创建默认大小集合实例时使用
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.
     * 存储ArrayList元素的数组缓冲区,ArrayList的容量是这个数组缓冲区的长度。
     * 当添加第一个元素时,空ArrayList都将被扩展为默认容量。
     * elementData定义为transient的优势,是可以自己根据size序列化真实的元素,而不是根据数组的长度
     * 序列化元素,减、少了空间占用。
     */
    transient Object[] elementData; // non-private to simplify nested class access

    /**
     * The size of the ArrayList (the number of elements it contains).
     * 集合中存取的元素个数
     * @serial
     */
    private int size;
构造方法
 /**
     * Constructs an empty list with the specified initial capacity.
     * 给定初始容量构造集合 
     * @param  initialCapacity  the initial capacity of the list
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
        	// 如果传入的初始容量大于0,就新建一个数组存储元素
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
        	// 如果传入的初始容量等于0,使用空数组EMPTY_ELEMENTDATA
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
        	// 如果传入的初始容量小于0,抛出异常
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

    /**
     * Constructs an empty list with an initial capacity of ten.
     * 构造默认初始容量为10的集合
     */
    public ArrayList() {
    // 如果没有传入初始容量,则使用空数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA
    // 使用这个数组不会在创建的第一时间就生成集合,而是在添加第一个元素的时候会扩容到默认大小10,
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    /**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     * 通过一个既有的集合创建新的集合
     * @param c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public ArrayList(Collection<? extends E> c) {
	    // 集合转数组
	       elementData = c.toArray();
        if ((size = elementData.length) != 0) {
        	// 检查c.toArray()返回的是不是Object[]类型,如果不是,重新拷贝成Object[].class类型
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
             // 如果c的空集合,则初始化为空数组EMPTY_ELEMENTDATA
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }
add(E e) 添加方法与扩容
public boolean add(E e) {
    // 检查是否需要扩容
    ensureCapacityInternal(size + 1);
    // 把元素插入到最后一位
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    // 如果是空数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA,就初始化为默认大小10
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

    if (minCapacity - elementData.length > 0)
        // 扩容
        grow(minCapacity);
}

private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    // 新容量为旧容量的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 如果新容量发现比需要的容量还小,则以需要的容量为准
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    // 如果新容量已经超过最大容量了,则使用最大容量
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // 以新容量拷贝出来一个新数组
    elementData = Arrays.copyOf(elementData, newCapacity);
}

        还有将元素添加到指定位置的add(int index, E element)方法和求两个集合并集的addAll方法,代码类似于add(E e),不再赘述。

几种删除方法
/**
	*删除指定位置的元素,没有缩容过程
*/
public E remove(int index) {
    // 检查是否越界
    rangeCheck(index);
    modCount++;
    // 获取index位置的元素
    E oldValue = elementData(index);
    // 如果index不是最后一位,则将index之后的元素往前挪一位
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index, numMoved);
    // 将最后一个元素删除,帮助GC
    elementData[--size] = null; // clear to let GC do its work
    // 返回旧值
    return oldValue;
}

/**
	*删除指定元素值的元素,时间复杂度为O(n)。
*/
public boolean remove(Object o) {
    if (o == null) {
        // 遍历整个数组,找到元素第一次出现的位置,并将其快速删除
        for (int index = 0; index < size; index++)
            // 如果要删除的元素为null,则以null进行比较,使用==
            if (elementData[index] == null) {
                fastRemove(index);
                return true;
            }
    } else {
        // 遍历整个数组,找到元素第一次出现的位置,并将其快速删除
        for (int index = 0; index < size; index++)
            // 如果要删除的元素不为null,则进行比较,使用equals()方法
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}

/**
	*求两个集合的交集。
*/
private void fastRemove(int index) {
    // 少了一个越界的检查
    modCount++;
    // 如果index不是最后一位,则将index之后的元素往前挪一位
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index, numMoved);
    // 将最后一个元素删除,帮助GC
    elementData[--size] = null; // clear to let GC do its work
}

public boolean retainAll(Collection<?> c) {
    // 集合c不能为null
    Objects.requireNonNull(c);
    // 调用批量删除方法,这时complement传入true,表示删除不包含在c中的元素
    return batchRemove(c, true);
}

/**
* 批量删除元素
* 
* complement为true表示删除c中不包含的元素
* complement为false表示删除c中包含的元素
*/
private boolean batchRemove(Collection<?> c, boolean complement) {
    final Object[] elementData = this.elementData;
    // 使用读写两个指针同时遍历数组
    // 读指针每次自增1,写指针放入元素的时候才加1
    // 这样不需要额外的空间,只需要在原有的数组上操作就可以了
    int r = 0, w = 0;
    boolean modified = false;
    try {
        // 遍历整个数组,如果c中包含该元素,则把该元素放到写指针的位置(以complement为准)
        for (; r < size; r++)
            if (c.contains(elementData[r]) == complement)
                elementData[w++] = elementData[r];
    } finally {
        // 正常来说r最后是等于size的,除非c.contains()抛出了异常
        if (r != size) {
            // 如果c.contains()抛出了异常,则把未读的元素都拷贝到写指针之后
            System.arraycopy(elementData, r,
                             elementData, w,
                             size - r);
            w += size - r;
        }
        if (w != size) {
            // 将写指针之后的元素置为空,帮助GC
            for (int i = w; i < size; i++)
                elementData[i] = null;
            modCount += size - w;
            // 新大小等于写指针的位置(因为每写一次写指针就加1,所以新大小正好等于写指针的位置)
            size = w;
            modified = true;
        }
    }
    // 有修改返回true
    return modified;
}

/**
* 求两个集合的单方向差集,只保留当前集合中不在c中的元素,不保留在c中不在当前集体中的元素。
*/
public boolean removeAll(Collection<?> c) {
    // 集合c不能为空
    Objects.requireNonNull(c);
    // 同样调用批量删除方法,这时complement传入false,表示删除包含在c中的元素
    return batchRemove(c, false);
}
更改元素方法和查询方法
    /**
     * Replaces the element at the specified position in this list with
     * the specified element.
     * 根据索引和新元素值更改集合元素值
     * @param index index of the element to replace
     * @param element element to be stored at the specified position
     * @return the element previously at the specified position
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E set(int index, E element) {
        rangeCheck(index); //检查索引范围

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }
   /**
	 * 删除指定元素值的元素,时间复杂度为O(n)。
     */
    public E get(int index) {
    // 检查是否越界
    rangeCheck(index);
    // 返回数组index位置的元素
    return elementData(index);
	}

	private void rangeCheck(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
	}

	E elementData(int index) {
    return (E) elementData[index];
	}

  • JDK7中你编写ArrayList list = new ArrayList();//底层创建了长度是10的Object[]数组elementData 你首次添加元素,编写list.add(123);实际上就等于elementData[0] = new Integer(123); 如果某次添加元素导致底层elementData数组容量不够,则会扩容。默认情况下,扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中。结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(int capacity);
  • JDK8中ArrayList的变化:当你创建集合时,编写ArrayList list = new ArrayList();这时底层Object[] elementData初始化为{}。并没有创建长度为10的数组。添加元素list.add(123);//第一次调用add()时,底层才创建了长度10的数组,并将数据123添加到elementData[0]后续的添加和扩容操作与jdk 7 无异。
  • 小结:jdk7中的ArrayList的对象的创建类似于单例的饿汉式,而jdk8中的ArrayList的对象的创建类似于单例的懒汉式,延迟了数组的创建,节省内存。

List接口实现类之LinkedList

LinkedList的体貌特征

对于频繁的插入或者删除元素的操作,建议使用LinkedList类,效率较高。新增方法有:

  • void addFirst(Object obj)
  • void addLast(Object obj)
  • Object getFirst()
  • Object getLast()
  • Object removeFirst()
  • Object removeLast()
LinkedList的底层源码分析:

LinkedList:不同于AraayList其内部没有声明数组,而是声明了一个双向链表用来存储数据,定义了Node类型的first和last,用于记录首末元素。同时定义内部类Node,作为LinkedList中保存数据的基本结构。Node除了保存数据,还定义了两个变量:(不太清楚双向链表和Node类是啥玩意的道友可以去学习下数据结构和算法,韩顺平老师有个专门针对于Java的数据结构系列视频还讲的阔以,毕竟是斗皇强者,bilibili就能找到)

  • prev变量记录前一个元素的位置
  • next变量记录下一个元素的位置
    在这里插入图片描述

List接口实现类之Vector

假慈悲,缅怀一下Vector
  • Vector是一个古老的集合,JDK1.0就有了。大多数操作与ArrayList相同,区别之处在于Vector是线程安全的,属于强同步类(Synchronized),开销比ArrayList大,访问要慢。Vector每次扩容请求其大小的2倍空间,而ArrayList是1.5倍。Vector还有一个子类Stack,是一个栈,但现在也被抛弃了,当需要使用栈时往往都会用LinkedList自己写一个。
  • 总之,在各种List中,最好把ArrayList作为第一选择,当你针对某类数据插入、删除频繁时,可以考虑使用LinkedList;Vector,走好不送。当你必须考虑线程安全问题时,后面会有讲到集合工具类中有专门的方法可以使得ArrayList类变成线程安全的,性能更好。
List集合常用方法测试
package com.learnjiawa.jihe;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 *   1.List接口中的常用方法
 */
public class ListTest {

    /*
void add(int index, Object ele):在index位置插入ele元素
boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
Object get(int index):获取指定index位置的元素
int indexOf(Object obj):返回obj在集合中首次出现的位置
int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
Object remove(int index):移除指定index位置的元素,并返回此元素
Object set(int index, Object ele):设置指定index位置的元素为ele
List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合

总结:常用方法
增:add(Object obj)
删:remove(int index) / remove(Object obj)
改:set(int index, Object ele)
查:get(int index)
插:add(int index, Object ele)
长度:size()
遍历:① Iterator迭代器方式
     ② 增强for循环
     ③ 普通的循环

     */
    @Test
    public void test3(){
        ArrayList list = new ArrayList();
        list.add(123);
        list.add(456);
        list.add("AA");

        //方式一:Iterator迭代器方式
        Iterator iterator = list.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

        System.out.println("***************");

        //方式二:增强for循环
        for(Object obj : list){
            System.out.println(obj);
        }

        System.out.println("***************");

        //方式三:普通for循环
        for(int i = 0;i < list.size();i++){
            System.out.println(list.get(i));
        }



    }


    @Test
    public void test2(){
        ArrayList list = new ArrayList();
        list.add(123);
        list.add(456);
        list.add("AA");
        list.add(new Person("Tom",12));
        list.add(456);
        //int indexOf(Object obj):返回obj在集合中首次出现的位置。如果不存在,返回-1.
        int index = list.indexOf(4567);
        System.out.println(index);

        //int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置。如果不存在,返回-1.
        System.out.println(list.lastIndexOf(456));

        //Object remove(int index):移除指定index位置的元素,并返回此元素
        Object obj = list.remove(0);
        System.out.println(obj);
        System.out.println(list);

        //Object set(int index, Object ele):设置指定index位置的元素为ele
        list.set(1,"CC");
        System.out.println(list);

        //List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的左闭右开区间的子集合
        List subList = list.subList(2, 4);
        System.out.println(subList);
        System.out.println(list);


    }


    @Test
    public void test1(){
        ArrayList list = new ArrayList();
        list.add(123);
        list.add(456);
        list.add("AA");
        list.add(new Person("Tom",12));
        list.add(456);

        System.out.println(list);

        //void add(int index, Object ele):在index位置插入ele元素
        list.add(1,"BB");
        System.out.println(list);

        //boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
        List list1 = Arrays.asList(1, 2, 3);
        list.addAll(list1);
//        list.add(list1);
        System.out.println(list.size());//9

        //Object get(int index):获取指定index位置的元素
        System.out.println(list.get(0));

    }


}

去看该系列文章下一篇: 六段斗之气–Collection的子接口:Set接口.

参考文献

[1]Bruce Eckel.Java编程思想(第4版)[M].机械工业出版社,2008:459-524.

更多

对我的文章感兴趣,持续更新中…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 集合中添加元素可以使用 add() 方法。 例如: ```java List<String> list = new ArrayList<String>(); list.add("item1"); list.add("item2"); ``` 也可以使用 addAll() 方法将一个集合中的所有元素添加到另一个集合中。 例如: ```java List<String> list1 = new ArrayList<String>(); list1.add("item1"); list1.add("item2"); List<String> list2 = new ArrayList<String>(); list2.add("item3"); list2.add("item4"); list1.addAll(list2); ``` 这样,list1 中就包含了 "item1","item2","item3" 和 "item4"。 ### 回答2: Java集合类是Java编程语言中最重要的数据结构之一。它们提供了一种方便、快速和高效地管理数据的方法。集合类的主要作用就是存储和操作数据,Java集合类的一个关键接口就是Collection接口。在Java中,Collection接口是所有集合类的根接口,因此,学习使用Collection接口是理解和使用Java集合类的基础。 往集合中添加元素是Collection接口的基本操作之一。在Java中,我们可以使用add()方法将元素添加到集合中。add()方法是Collection接口中的一个标准方法,它用于将一个元素添加到集合中。在使用add()方法时,我们只需要将要添加的元素传递给这个方法即可。例如: ```Java ArrayList<String> list = new ArrayList<>(); list.add("Java"); list.add("Python"); list.add("PHP"); ``` 在这个例中,我们使用ArrayList集合类初始化了一个list对象,然后使用add()方法向集合中添加了三个元素,分别是”Java”,”Python”和”PHP”。 除了add()方法之外,Collection接口还提供了许多其他的方法用于向集合中添加元素,如addAll()、offer()和push()等。这些方法都可以实现向集合中添加元素的功能,具体选择哪个方法,取决于具体的需求。例如,addAll()方法可以添加一个集合中的所有元素,而push()方法只能添加一个元素到栈顶。 总的来说,学习Java集合类中Collection接口中添加元素的方法很重要,它是理解Java集合类的基础之一。掌握添加元素的各种方法,可以让我们更加高效地管理和操作Java集合中的数据。 ### 回答3: Java集合类是Java开发中非常常用的数据类型,而往集合中添加元素是其基本操作之一。其中,Collection接口Java集合类中最基本的接口,所有的集合类都可以通过实现该接口来实现元素的添加、删除、查找等操作。 往一个集合中添加元素,通常可以用add()方法来完成。在Collection接口中,add()方法用于向集合中添加一个元素。例如,我们可以使用以下代码向一个List类型的集合中添加一个元素: ```java List<String> list = new ArrayList<String>(); list.add("Java"); ``` 上述代码中,我们创建了一个ArrayList类型的list集合,并使用add()方法向其中添加了一个字符串元素"Java"。 需要注意的是,在使用add()方法时,需要注意元素类型的匹配。例如,如果我们创建的集合类型为List<Integer>,则不能添加其他类型的元素,否则会编译错误。 此外,Collection接口中还提供了addAll()方法,用于将一个集合中的所有元素批量添加到另一个集合中。例如,我们可以使用以下代码将一个数组中的所有元素添加到一个Set类型的集合中: ```java Set<Integer> set = new HashSet<Integer>(); Integer[] arr = new Integer[]{1, 2, 3, 4}; set.addAll(Arrays.asList(arr)); ``` 上述代码中,我们首先创建了一个HashSet类型的set集合,然后使用addAll()方法将数组arr中所有的元素添加到set集合中。 除了使用add()和addAll()方法往集合中添加元素外,Java集合类还提供了其他方法用于添加、删除、查找元素,如remove()、contains()等。不同类型的集合类有着不同的实现方法,开发者可以根据具体需求选择合适的集合类型和操作方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值