Java-集合框架Collection之List(一)

List接口

List接口继承了Collection接口

List接口
List接口存放的元素有序且允许有重复,Set接口存放的元素则是无序不重复
说明:
“有序”是指元素的存入顺序和和取出顺序相同,“无序”则是指存入顺序和取出顺序不同


        List<String> list = new ArrayList<String>();
        Set<String> set = new HashSet<String>();
        Set<Integer> setInt = new HashSet<Integer>();
        list.add("h");
        list.add("e");
        list.add("l");
        list.add("l");
        list.add("o");
        set.add("h");
        set.add("e");
        set.add("l");
        set.add("l");
        set.add("o");
        setInt.add(3);
        setInt.add(2);
        setInt.add(0);
        setInt.add(5);
        setInt.add(1);
        for (int i = 0 ; i < list.size(); i++ ) {
            System.out.print(list.get(i));
        }
        System.out.println();
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next());
        }
        System.out.println();
        Iterator<Integer> iteratorInt = setInt.iterator();
        while (iteratorInt.hasNext()) {
            System.out.print(iteratorInt.next());
        }

输出结果:

hello
eolh
01235

可以看到当把String类型的相同数据分别放到List和Set集合中,再取出来两者就不一样了。List集合按照存入的顺序取出;Set集合则按照英文字母的顺序取出。
如果存入Set集合的数据是Integer类型,则按照整数从小到大的顺序取出。

常用方法
  • 添加
    boolean add(E e);
    boolean addAll(Collection< ? extends E> c);
  • 删除
    boolean remove(Object o);
    boolean removeAll(Collection< ?> c);
    boolean retainAll(Collection< ?> c);
  • 是否包含
    boolean contains(Object o)
    boolean containsAll(Collection< ? > c)
  • 清空
    void clear();
  • 获取单个元素和迭代器
    E get(int index);
    Iterator< E > iterator();//也可以用for循环依次获取每个元素
  • 判空和获取大小
    int size();
    boolean isEmpty();

List接口的实现类ArrayList

ArrayList类
ArrayList是List接口最常用到的一个实现类,ArrayList列表对象实际上存储在一个Object类型的数组,当列表对象变化时,新建一个数组,再通过copyof方法覆盖旧的数组,所以ArrayList就像一个可变大小的数组。

ArrayList源码 :

ArrayList属性:

private transient Object[] elementData;//ArrayList内的元素
private int size;//元素的数量

ArrayList提供了三个构造方法:

/**如果指定了初识的容量,构造一个指定大小的空列表*/
public ArrayList(int initialCapacity) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal   Capacity: "+initialCapacity);
        this.elementData = new Object[initialCapacity];//创建一个长度为指定容量的临时数组
    }
private static final Object[] EMPTY_ELEMENTDATA = {};

/**如果未指定初识容量,则构造一个默认容量的空列表*/
public ArrayList() {
        super();
        this.elementData = EMPTY_ELEMENTDATA//现在的临时数组还是一个空数组,会在添加数据的时候进行判断并设置初识的容量
    }
//构造一个包含指定Collection元素的列表,即ArrayList放Collection元素
public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();//初始化临时数组
        size = elementData.length;//列表长度
        //可能临时数组不是Object[]类型,
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    }

    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

添加元素:

private static final int DEFAULT_CAPACITY = 10;//初始容量
/*添加*/
public boolean add(E e) {
  ensureCapacityInternal(size + 1);  // Increments modCount!! 
  elementData[size++] = e;//在数组的尾部添加元素
  return true;
    }
/*确保容量*/  
private void ensureCapacityInternal(int minCapacity) {
        /*判断是否指定初始的容量*/
        if (elementData == EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//比较默认容量和(元素数量size+1)的大小,取较大的值作为添加元素后ArrayList的容量
        }
        ensureExplicitCapacity(minCapacity);
    }

 protected transient int modCount = 0;//定义在AbstractList接口中
/*确定容量*/
private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//The number of times this list has been structurally modified.
    //这是对modCount的解释,意为记录list结构被改变的次数
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
/*核心方法*/
private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);//新的容量:(元素数量+元素数量/2)
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;//添加元素后(size+1)未超过给定的容量,不用增加容量
        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);//elementData指向新容量的数组,旧的数组被丢弃
    }
/*能分配的最大的容量*/
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

    /**
     * The maximum size of array to allocate.
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     * 减去8是因为VMs保留了一些头部字段
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
  //在java.lang.Integer类中常量MIN_VALUE、MAX_VALUE如下:
   public static final int   MIN_VALUE = 0x80000000;//整型取值区间下界:-2147483648
   public static final int   MAX_VALUE = 0x7fffffff;//整型取值区间上界:2147483647

删除元素:分为按位置删除和按元素删除

根据位置删除:

public E remove(int index) {
        rangeCheck(index);//检查是否超过ArrayList长度
        modCount++;//记录list结构被改变的次数
        E oldValue = elementData(index);//保留要删除的元素
        int numMoved = size - index - 1;设置新数组长度-1
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index, numMoved);要删除元素后面的值往前移一位
        elementData[--size] = null; // clear to let GC do its work末尾元素置null回收

        return oldValue;//返回要删除的元素的值
    }
/*检测位置*/
private void rangeCheck(int index) {
        if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

根据元素删除:

public boolean remove(Object o) {
        if (o == null) {//删除null的元素
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }
    /*删除元素*/
private void fastRemove(int index) {
        //不用进行边界处理
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index, numMoved);
        elementData[--size] = null; // clear to let GC do its work
    }

根据元素删除和根据位置删除的区别:
根据元素删除返回的是true或false
根据位置删除返回的是要删除的元素

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wwwjfplus

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值