集合用数组的实现方式
数组的长度是固定的,所以在实际使用过程中导致在满数组后无法再添加,这时可以使用集合。
实现类:自定义一个集合类,在数组容量满的时候自动扩容,这个是list的底层实现
public class MyArray {
private int [] array = new int[10];
private int index = 0;
//将元素添加到初始数组中,同时在添加之前对数组下标进行判断,调用扩容方法
public void add(int i) {
extendArray();
array[index++] = i;
}
//获取数组中的,每一个值
public int get(int i) {
return array[i];
}
//扩容方法
public void extendArray() {
//如果数组装满
if(index >= array.length) {
//创建一个新的数组,容量是之前的两倍
int [] temp = new int[array.length * 2];
//调用数组复制的方法
System.arraycopy(array, 0, temp, 0, array.length);
//将之前的数组指向新建的数组
array = temp;
}
}
测试类:
public static void main(String[] args) {
MyArray my = new MyArray();
for(int i = 0;i<20;i++) {
my.add(i);
}
for(int i = 0;i<20;i++) {
System.out.println(my.get(i));
}
}
List的特点
- 元素有序
- 有角标,可以利用角标精确的访问集合中的每一个元素
- 允许存储重复的元素
- 允许存储多个null元素
- 在list集合中,有两个常用的实现类:ArrayList,LinkedList
迭代器
在集合中有两个迭代器:Iterator和ListIterator
Iterator只适合用来遍历集合,无法在遍历的过程中对集合进行更新
public static void main(String[] args) {
ArrayList list = new ArrayList();
Student s1 = new Student(21, "aaa");
list.add(s1);
list.add(123);
list.add("asd");
list.add("zxc");
Iterator it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
遍历结果:
Student [age=21, name=aaa]
123
asd
zxc
ListIterator中有更丰富的方法,可以在遍历的过程中对集合进行增(add),删(remove),替换(set);
在遍历的过程中增加元素:
public static void main(String[] args) {
ArrayList my = new ArrayList();
my.add("corejava");
my.add("sql");
my.add("spring");
System.out.println(my);
ListIterator lt = my.listIterator();
while(lt.hasNext()) {
String str =(String) lt.next();
//添加到判断元素的后面,而不是在集合的末尾添加
if(str.equals("sql"))
//迭代器的add方法
lt.add("jdbc");
}
System.out.println(my);
}
这里是运行结果
[corejava, sql, spring]
[corejava, sql, jdbc, spring]
删除List集合中的重复元素
当这个元素是一个自定义的类时,可以在实体类中自定义一个equals方法或者在编辑器中调用equals方法。
编辑器调用:
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
自定义:
public boolean equals(Object obj) {
if(!(obj instanceof Student)) {
throw new RuntimeException();
}
Student other = (Student)obj;
if(this.name.equals(other.name) && this.age == other.age) {
return true;
}
return false;
}
如果没有在实体类中重写equals方法:
ArrayList<Student> list = new ArrayList();
Student s1 = new Student(21, "aaa");
list.add(s1);
boolean f = list.remove(new Student(21, "aaa"));
System.out.println(f);
打印结果是false
在重写equals方法后:
打印结果是true
这里的集合,需要让里面的元素是通一种类型,不然在系统的equals方法中,会返回false,在自定义的方法中会报错:RunTimeException。
List集合常用的方法都在api中可以查得到。
- 添加元素方法:void add(int index,Object obj)
- 删除元素方法:Object remove(int index)
- 修改元素方法:Object set(int index,Object obj)
- 获取元素方法:Object get(int index)
ArrayList集合:实现了List集合,具备List集合的特点,底层采用可变数组结构,查询遍历效率高,增删效率比较低。
LinkedList集合(类):实现了List集合,具备List集合的特点,底层使用链表结构(链表的特点:有头有尾)
,查询遍历元素效率比较低,增删元素的效率比较高
Vector和ArrayList底层都是采用可变数组结构,但是Vector线程是安全的,线程安全带来的结果就是效率低
ArrayList和LinkedList的方法具体用法可见API。