今天我带大家一起学习java中的容器部分,首先我们来看一下ArrayList。
我们需要先明确的是,有些时候我们需要不断的向一个库中添加或者删除元素,我们首先自然而然想到的就是数组,然而数组并不支持扩展内存,我们只能初始化固定数组的长度,然而我们往往会造成内存空间的浪费,或者我们创建数组的长度无法满足我们实际情况的需要,这时java为我们提供了容器这个概念,我们今天首先了解下其中的ArrList
List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小.
每个 ArrayList 实例都有一个容量。该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向 ArrayList 中不断添加元素,其容量也自动增长。并未指定增长策略的细节,因为这不只是添加元素会带来分摊固定时间开销那样简单。
我们先来看下ArrayList里的方法
接下来我们用代码实现一遍
package com.wanghaixueStudy.cn;
import java.util.ArrayList;
/**
* 本程序我们来学习一下ArrayList的基本用法
* @author lover
*
*/
class student{ //创建一个类资源
private String name;
private boolean sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean getSex() {
return sex;
}
public void setSex(boolean sex) {
this.sex = sex;
}
}
public class ArraylistText {
public static void main(String[] args) {
//创建三个student对象
student s1=new student();
s1.setName("王海学");
s1.setSex(true);
student s2=new student();
s2.setName("邵玥");
s2.setSex(false);
student s3=new student();
s3.setName("猪");
s3.setSex(true);
//创建ArrayList集合
ArrayList arr=new ArrayList();
//增-->向arr容器中增加student对象
arr.add(s1);
arr.add(s2);
arr.add(s3);
//查-->我们查询arr容器里的对象
for(int i=0;i<arr.size();i++){
student s=(student) arr.get(i);
System.out.println(s.getName()+":"+s.getSex());
}
//删-->删除arr中的对象
arr.remove(0);
arr.remove(s3);
for(int i=0;i<arr.size();i++){
student s=(student) arr.get(i);
System.out.println(s.getName()+":"+s.getSex());
}
arr.add(s1);
arr.add(s3);
//判断arr容器里是否包含某一对象
System.out.println(arr.contains(s2));
//将容器转换为数组
Object obj[]=arr.toArray();
}
}
看一下输出结果
王海学:true
邵玥:false
猪:true
邵玥:false
true
(二)LinkerList
List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。
所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。
package com.wanghaixueStudy.cn;
import java.util.LinkedList;
/**
* 本程序我们学习LinkerList
* @author lover
*
*/
class student{ //创建一个类资源
private String name;
private boolean sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean getSex() {
return sex;
}
public void setSex(boolean sex) {
this.sex = sex;
}
}
public class LinkerListText {
public static void main(String[] args) {
//创建LinkerList容器
LinkedList lin=new LinkedList();
//创建三个student对象
student s1=new student();
s1.setName("王海学");
s1.setSex(true);
student s2=new student();
s2.setName("邵玥");
s2.setSex(false);
student s3=new student();
s3.setName("猪");
s3.setSex(true);
//增-->向arr容器中增加student对象
lin.add(s1);
//我们还可以向开始添加 和最后添加
lin.addFirst(s2);
lin.addLast(s3);
//查-->我们查询arr容器里的对象
for(int i=0;i<lin.size();i++){
student s=(student) lin.get(i);
System.out.println(s.getName()+":"+s.getSex());
}
//删-->删除arr中的对象
lin.remove(0);
lin.remove(s3);
for(int i=0;i<lin.size();i++){
student s=(student) lin.get(i);
System.out.println(s.getName()+":"+s.getSex());
}
lin.add(s1);
lin.add(s3);
//判断arr容器里是否包含某一对象
System.out.println(lin.contains(s2));
}
}
我们看下输出结果
邵玥:false
王海学:true
猪:true
王海学:true
false
相比与ArrayList,LinkerList不是按物理结构排的,它采用双向链表的形式,头指向前一个元素的尾,前一个元素的尾同样指向这个元素的头。因而增加了很多的方法,小伙伴们可以一一尝试。
(三)ArrayList和LinkerList的区别
1、同步性
ArrayList,LinkedList是不同步的,而Vector是的。所以如果要求线程安全的话,可以使用ArrayList或LinkedList,可以节省为同步而耗费开销。但在多线程的情况下,有时候就不得不使用Vector了。当然,也可以通过一些办法包装ArrayList,LinkedList,使他们也达到同步,但效率可能会有所降低。
2、数据增长
从内部实现机制来讲ArrayList和Vector都是使用Objec的数组形式来存储的。当你向这两种类型中增加元素的时候,如果元素的数目超出了内部数组目前的长度它们都需要扩展内部数组的长度,Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%,所以最后你获得的这个集合所占的空间总是比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用Vector有一些优势,因为你可以通过设置集合的初始化大小来避免不必要的资源开销。
3、检索、插入、删除对象的效率
ArrayList和Vector中,从指定的位置(用index)检索一个对象,或在集合的末尾插入、删除一个对象的时间是一样的,可表示为O(1)。但是,如果在集合的其他位置增加或移除元素那么花费的时间会呈线形增长:O(n-i),其中n代表集合中元素的个数,i代表元素增加或移除元素的索引位置。为什么会这样呢?以为在进行上述操作的时候集合中第i和第i个元素之后的所有元素都要执行(n-i)个对象的位移操作。
LinkedList中,在插入、删除集合中任何位置的元素所花费的时间都是一样的—O(1),但它在索引一个元素的时候比较慢,为O(i),其中i是索引的位置。
所以,如果只是查找特定位置的元素或只在集合的末端增加、移除元素,那么使用Vector或ArrayList都可以。如果是对其它指定位置的插入、删除操作,最好选择LinkedList