精华内容
下载资源
问答
  • ArryList

    2019-04-20 17:47:15
    数组复制 复制层级 让另一个事物,具备另一个事物的相同属性,这就叫做拷贝,或者说复制。 要理解程序中的拷贝,首先要明白名称和内存的这两个部分。 Objectnamememory 一般来说,我们通过name去操作body,但是全部...

    数组复制

    复制层级

    让另一个事物,具备另一个事物的相同属性,这就叫做拷贝,或者说复制。

    要理解程序中的拷贝,首先要明白名称和内存的这两个部分。

    Object
    name
    memory

    一般来说,我们通过name去操作body,但是全部的信息都是在body中。

    • 浅拷贝

    浅拷贝,所谓的浅,指的是不私有,这种拷贝,没有独立的自我空间。

    Object
    name
    body
    copy

    实体并没有发生变化。

    public static void main(String[] args){
        Object old = new Object();
        Object copy = old;
    }
    

    这种情况,好像多了一个对象,但是实体并没有增多。每个对象的操作,另一个能够感知,也会受到影响。

    好比一间房子,两把钥匙。

    进来的人,能够看到,也能装修,但是却不能阻止别人动手。

    • 深拷贝

    浅拷贝存在的问题,就是没有隐私。你的修改,可能过一会,就又被改动了。

    把浅拷贝看做入口分离,深拷贝就是全分离,就连实体也是全新的。

    浅拷贝:单一对象,引用复制,引用和实体多对一

    深拷贝:多个对象,属性复制,引用和实体一对一

    内存拷贝

    使用深拷贝,就会是对象之间的属性复制,一般操作是这样的。

    • 手工拷贝
    public static void main(String[] args){
        Person person = new Person();
        person.name = "name";
        person.age = 99;
        Person copy = new Person();
        copy.name = person.name;
        copy.age = person.age;
    }
    

    也即是这样的流程
    在这里插入图片描述

    1. 通过名称查询实体属性
    2. 通过名称设置已获取的属性
    • 内存拷贝

    对于对象,手工拷贝挺好的,但是数组作为连续内存空间,何不直接进行内存拷贝。

        public static void main(String[] args) {
            int[] oldArray = new int[]{1,2,3};
            int[] newArray = new int[3];
            System.arraycopy(oldArray,0,newArray,0,3);
            System.out.println(Arrays.toString(newArray));
        }
    

    通过操作系统直接内存拷贝,减少人工操作,更加快速。

    数组拷贝

    • System.arraycopy
    paramIndex description
    1 原数组
    2 开始复制索引
    3 目的数组
    4 复制起点索引
    5 复制元素个数
    • 索引不能越界
    • 长度不能超过原数组长度,也不能超过目的数组长度
    • 原数组可以就是目的数组
    • Arrays.copyOf
        public static int[] copyOf(int[] original, int newLength) {
            int[] copy = new int[newLength];
            System.arraycopy(original, 0, copy, 0,
                             Math.min(original.length, newLength));
            return copy;
        }
    

    进一步封装了,简化参数,自带扩容功能。

    初始化方法

    指定长度

        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);
            }
        }
    

    其实就是新建了默认的定长数组。

    默认方法

        public ArrayList() {
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
        }
    

    默认情况下是{}空数组,不过添加时会自动扩容为10

    元素构造

        public ArrayList(Collection<? extends E> c) {
            elementData = c.toArray();
            if ((size = elementData.length) != 0) {
                if (elementData.getClass() != Object[].class)
                    elementData = Arrays.copyOf(elementData, size, Object[].class);
            } else {
                this.elementData = EMPTY_ELEMENTDATA;
            }
        }
    

    把传入的集合作为原始数组,还有类型转换。

    扩容办法

    检测办法

        private void ensureCapacityInternal(int minCapacity) {
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
            }
            ensureExplicitCapacity(minCapacity);
        }
    

    其中DEFAULT_CAPACITY就是默认的10了,如果初始化时是空数组,就会直接初始化为10

    是否扩容

        private void ensureExplicitCapacity(int minCapacity) {
            modCount++;
            if (minCapacity - elementData.length > 0)
                grow(minCapacity);
        }
    

    minCapacity一般传入的是size+1,也就是再添加一个元素是否越界。

    扩容方法

        private void grow(int minCapacity) {
            int oldCapacity = elementData.length;
            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);
        }
    
    1. 默认扩容1.5
    2. 指定扩容和默认扩容选择容量大的进行扩容
    3. 越界会有操作
    4. 替换原有内核数据

    这里明确两个点:默认以1.5倍进行扩容,扩容实际上就是替换更大容量存储实体。

    这里也就明白了为何Buffer不可扩容,因为它的存储实体是final的,不可扩容啊。

    越界处理

        private static int hugeCapacity(int minCapacity) {
            if (minCapacity < 0) // overflow
                throw new OutOfMemoryError();
            return (minCapacity > MAX_ARRAY_SIZE) ?
                Integer.MAX_VALUE :
                MAX_ARRAY_SIZE;
        }
    

    这里会提示OOM,不过也会照常进行返回。

        private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    

    也就是说,超过了MAX_ARRAY_SIZE临界值,就直接Integer.MAX_VALUE,下次就不好扩容了。

    元素添加

    直接添加

        public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
        }
    

    索引添加

        public void add(int index, E element) {
            rangeCheckForAdd(index);
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            System.arraycopy(elementData, index, elementData, index + 1,
                             size - index);
            elementData[index] = element;
            size++;
        }
    

    rangeCheckForAdd就是做了个index索引合法性校验。

    可以看到,判断扩容后,只是把后续的元素挪动,空出该索引置放元素。

    全部添加

        public boolean addAll(Collection<? extends E> c) {
            Object[] a = c.toArray();
            int numNew = a.length;
            ensureCapacityInternal(size + numNew);  // Increments modCount
            System.arraycopy(a, 0, elementData, size, numNew);
            size += numNew;
            return numNew != 0;
        }
    

    唯一值的注意的,就是扩容的长度变更和值设置变成了数组拷贝。

    元素移除

    索引移除

        public E remove(int index) {
            rangeCheck(index);
            modCount++;
            E oldValue = elementData(index);
            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
            return oldValue;
        }
    

    还是索引判断和元素挪移。

    对象移除

        public boolean remove(Object o) {
            if (o == 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;
        }
    

    可以看到,ArrayList中是可以存储null值的。

        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
        }
    

    具体的移除操作,就是和扩容相反的压缩,让元素紧密。

    索引对照

    索引到对象

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

    数组直接访问,没问题。

    对象到索引

        public int indexOf(Object o) {
            if (o == null) {
                for (int i = 0; i < size; i++)
                    if (elementData[i]==null)
                        return i;
            } else {
                for (int i = 0; i < size; i++)
                    if (o.equals(elementData[i]))
                        return i;
            }
            return -1;
        }
    

    遍历检索,找不到返回-1

    倒序查找

        public int lastIndexOf(Object o) {
            if (o == null) {
                for (int i = size-1; i >= 0; i--)
                    if (elementData[i]==null)
                        return i;
            } else {
                for (int i = size-1; i >= 0; i--)
                    if (o.equals(elementData[i]))
                        return i;
            }
            return -1;
        }
    

    元素包含

        public boolean contains(Object o) {
            return indexOf(o) >= 0;
        }
    

    复用原来的索引查找进行判断。

    小结

    • 默认扩容1.5倍步进
    • 可以存储null
    • 以更大容量容器进行数据复制和替换,实现扩容

    数据复制,数据量大时,这种复制办法爽到不行。

    展开全文
  • arrylist

    2011-11-06 22:34:44
    优点 1。支持自动改变大小的功能 2。可以灵活的插入元素 3。可以灵活的删除元素 添加元素 1. public virtual int Add(object value); 将对象添加到 ArrayList 的结尾处 ArrayList aList = new ...aList

    优点

    1。支持自动改变大小的功能

    2。可以灵活的插入元素

    3。可以灵活的删除元素

    添加元素

    1.  public virtual int Add(object value);

    将对象添加到 ArrayList 的结尾处

    ArrayList aList = new ArrayList();

    aList.Add("a");

    aList.Add("b");

    aList.Add("c");

    aList.Add("d");

    aList.Add("e");

    内容为a b c d e

    2.  public virtual void Insert(int index,object value);

      将元素插入 ArrayList 的指定索引处

    ArrayList aList = new ArrayList();

    aList.Add("a");

    aList.Add("b");

    aList.Add("c");

    aList.Add("d");

    aList.Add("e");

    aList.Insert(0,"aa");

    结果为aa a b  c d e

    3.  public virtual void InsertRange(int index,ICollection c);

       将集合中的某个元素插入 ArrayList 的指定索引处

      ArrayList aList = new ArrayList();

    aList.Add("a");

    aList.Add("b");

    aList.Add("c");

    aList.Add("d");

    aList.Add("e");

    ArrayList list2 = new ArrayList();

            list2.Add("tt");

    list2.Add("ttt");

    aList.InsertRange(2,list2);

    结果为a b tt ttt c d e

     

    展开全文
  • 自定义ArryList

    2019-05-12 23:39:49
    这个自定义的ArrayList是用来熟悉ArryList,体会ArryList的底层原理。 package cn.xiaomu_mycollection; /** * * @author 小沐 * */ public class SetArryList<E> { private Object[] elementData; // ...

    自定义ArrayList

    这个自定义的ArrayList是用来熟悉ArryList,体会ArryList的底层原理。

    package cn.xiaomu_mycollection;
    /**
     * 
     * @author 小沐
     *
     */
    public class SetArryList<E> {
    	private Object[] elementData;  // 数组
    	private int size;              // 长度
    	private static final int DEFALT_CAPACITY=10;    //默认数组长度
    	
    	public  SetArryList() {
    		elementData = new Object[DEFALT_CAPACITY]; 
    	}
    	
    	public SetArryList (int capacity) {
    		elementData = new Object[capacity]; 
    	}
    	
    	public void add(E object) {
    		elementData[size++] = object;
    	}
    	
    	@Override
    	public String toString() {  // 重写toString方法
    		// TODO Auto-generated method stub
    		StringBuilder sBuilder = new StringBuilder();
    		//a,b,c
    		sBuilder.append("[");
    		 for (Object object : elementData) { 
    			/*  如果不想打出空值,即可启用该循环
    			 * for (int i = 0; i < size; i++) { sBuilder.append(elementData[i]+","); } 
    			 */
    			sBuilder.append(object+",");
    		}
    		sBuilder.append("]");
    		
    		return sBuilder.toString();
    	}
    	
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		SetArryList s1 = new SetArryList(20);
    		s1.add("abc");
    		s1.add("数组");
    		
    		System.out.println(s1);
    	}
    
    }
    

     

    展开全文
  • C# arrylist

    2017-10-03 16:19:41
    动态数组、集合 arrylist  using system.collections;  声明长度 arrylist a =new arrylist(): 或 arrylist a =new arrylist(10);  增: arrylist a =new arrylist(10);   

              动态数组、集合    arrylist

              using system.collections;

     声明长度     arrylist a =new arrylist():            或           arrylist a =new arrylist(10);   

        增:   arrylist a =new arrylist(10); 

                a.add("嗯哼");

                 a.add("哈哈");

                 a.insert(0,"呵呵");

                 foreach( object obj in a)

                 {

                        console.writeline(obj);

                 } 

                 console.writeline(a.contains(1));

                 console.writeline(a.indexof(1));

                a.remove(0);

                a.remove(1.1);

                

                 foreach( object obj in a)

                 {

                        console.writeline(obj);

                 } 

                 a.clear();

                 

                 foreach( object obj in a)

                 {

                        console.writeline(obj);

                 } 

                


    展开全文
  • ArryList深度剖析

    2020-08-22 17:20:46
    ArryList深度剖析 一、底层数据结构 1、增删改查 增: 是先new一个新数组,然后将老的数组复制过去,在将新增内容填上 删:也要new一个新数组,然后将数组中要删除的元素的索引位置移除 改和查都不会new新数组 ...
  • C# ArryList实例

    2014-04-14 22:23:00
    C# ArryList实例 ArryList的声明,添加元素,删除元素,遍历元素,以及ArryList的转化为一维指定数组 代码及详解如下: using System;using System.Collections.Generic;using System.Text;using System....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,121
精华内容 1,648
关键字:

ArryList