问题所在:
数组在内存中是连续存储的。正是因为如此,我们想查找数组中的某个值是很方便的,只需要知道数组下标(注意:数组下标是从0开始),修改数组中的某个值也是很快的。但它也有缺点 缺点:删除和插入元素特别复杂,需要移动原来的元素,耗费时间。 必须首先知道数组的大小,声明数组时必须同时指明数组的长度,动态分配内存也是如此。
解决方法:
ArrayList类实现一个可增长的动态数组,位于 java.util.ArrayList。实现了 List 接口,它可以存储不同类型的对象(包括 null 在内),而数组则只能存放特定数据类型的值。
import java.util.ArrayList
ArrayList list = new ArrayList();
list.add(111);
list.add("abc");
list.remove(0);
-
List接口是Collection接口的子接口,List有一个重要的实现类–ArrayList类,List中的元素是有序排列的而且可重复,所以被称为是序列。
-
List可以精确的控制每个元素的插入位置,或删除某个位置元素,它的实现类ArrayList底层是由数组实现的。
-
List中有增删改查的方法。
-
List 是一个接口,不能实例化,需要一个具体类来实现实例化。
-
List 中的对象按照一定的顺序排放,里面的内容可以重复。 List 接口实现的类有:ArrayList(实现动态数组),Vector(实现动态数组),LinkedList(实现链表),Stack(实现堆栈)。
-
List 也可以存储不同类型的对象。
List list;//正确,list = null;
List list = new List();//是错误的用法
List list = new ArrayList();//正确,但是ArrayList向上转型为List,现在是一个List对象,ArrayList有的,List没有的属性和方法,就没办法使用了。 List list=new ArrayList()//正确,指明了类型。
这样写的好处:
-
可以随时根据需要换成其它的实现类,如 LinkedList或者Stack等等,这时你只要改变这一行就行了: List list = new LinkedList(); 其它使用了list地方的代码不需要改动。
-
因此这里强烈建议不要写成 ArrayList list = new ArrayList() 这样写之后想改就麻烦了(如果你实现了ArrayList特有的方法和属性,就要改很多东西),特别麻烦。 这也是面向对象的一个重要知识点:多态。接口和抽象类不能被实例化,但是它们可以创建一个指向自己的对象引用,接口和抽象类实现类或子类就在充当这样的角色 当然也可以通过实现类和子类实例化对象。其实这就是多态。上面的例子也正好体现了多态的优势
还有一种声明List的方法。
List<Integer> list = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
但这种声明也有一定的缺陷,使用了asList将数组转换为了List。 缺陷:使用工具类Arrays.asList()把数组转换成List时,不能使用其修改List相关的方法,它的add/remove/clear方法会抛出UnsupportOperationException异常 这是因为asList的返回对象是一个Arrays内部类,并没有实现List的修改方法。Arrays.asList体现的是适配器模式,只是转换接口,后台的数据仍是数组。